USB is very popular for interfacing with external devices. A problem with USB is, however, that it is very accessible, even for attackers. This project is about increasing the robustness against attacks via malicious USB devices. Existing tool lack desktop integratino which makes this project a good candidate to for GNOME. We can tighten the desktop integration to even make the protection capabilities even stronger.
USB was designed to standardise the connection of peripherals like keyboards, printers, disk drives etc. to personal computers, allowing them to communicate as well as supplying electric power.
This wide USB versatility leaded also to a worrying problem: given the fact that different device classes use the same connectors, one type of device can become more capable or more malicious without looking differently to the user.
In order to turn one device type into another a USB controller chip needs to be reprogrammed. But this can be considered an easy task because a lot of controller chips, like the thumb drives one, have no protection from such reprogramming.
The most famous USB attack that uses a reprogrammed firmware is called BadUSB. For example it's possible to:
- Transform a USB stick into a computer keyboard and issue commands on behalf of the logged-in user
- Transform a USB stick into a network card and change the DNS setting to redirect traffic.
Moreover BadUSB is not the only thing to worry about. As USB can be used to attach pretty much any device to the computer, it can be used to interact with many of the device drivers. Those drivers are often of questionable quality which increases the risk of being attacked. At the time of writing more than 250 CVEs are assigned for issues revolving around USB.
Academica has investigated the phenomenon of USB borne attack. Research papers like this one from Nir Nissim, Ran Yahalom, Yuval Elovici, USB-based attacks, Computers & Security (2017) investigate 29 types of USB-based attacks. Ranging from the oldest and most famous Rubber Ducky, that emulates a keyboard and injects a preloaded keystroke sequence, to the more recent and sophisticated like the TURNIPSCHOOL, that provides short range RF communication capability to software running on the host computer.
On top of that it has been shown that most people don't consider an USB memory stick a potential security threat. For example in a 2016 experiment at the University of Illinois, 297 infected USB sticks have been dropped outside of a parking lot. This classic social engineering attack had an estimated success rate of 45-98% with the first connected drive that called home in less than six minutes.
On the technical side, we can identify several areas that cause a bad USB device to become a problem.
Firstly, USB is "always on", meaning that you can plug in a device at any time and make Linux react, e.g. by loading the drivers for the device. This behaviour is not desirable from a security perspective, because the number of drivers a malicious USB devices can pull is large and so is the resulting attack surface. In particular, the argument can be made that new (USB) devices should only be allowed if the user is actually present. An active lock screen is an indicator for the user not being present. When it is likely that the user is not present, the necessity of activating a USB device is not as given as when the user actively using the machine.
Some devices, however, should probably always work. In particular, we might want have keyboards work always, because a keyboard might break and if the newly plugged in keyboard does not work, the user will be left locked out of the session. It may be possible to use some clever logic such as "only one external keyboard shall be allowed". It is currently unclear what other external devices should have more privileges. For example, do accessibilty devices exist that should be treated separately?
Secondly, USB is primitive, at least when compared to Thunderbolt. With Thunderbolt you can hand out a cookie which the device produce when its re-connected. USB does not have such a mechanism, so we cannot reliably re-identify a device to determine whether we know that device. We will thus have to deal with a bit of uncertainty.
Thirdly, the user expectation is that devices Just Work™. Rather than manually installing drivers or clicking through dialogues, the general expectation is that the Webcam, speaker, or keyboard works as soon as it has been plugged in. This expectation makes it hard to design for a UX that makes attacks harder.
How attacks using USB look like
- A Salaryman find a USB drive at the company entrance. Curious he attaches it to the Office PC. The USB drive is a Rubber Ducky - emulating a keyboard. It starts "typing". Opens a terminal, wget-malware, execute malware. Game over.
- A cleaning staff member got $ 500 to plug a USB thing in between the keyboard and the PC. Next time the user logs in, the whole keyboard session is monitored. (need to verify the exact behaviour of keyloggers. Go shopping)
- Danny Ocean is visiting a company under disguise. As soon as he has access to an unlocked PC he attaches the Bash Bunny. It is the size of a USB stick and can emulate different USB devices. While the host is coming back with the coffee, the device does it's magic. Emulating a keyboard, opening a command line, starting a script there. Then emulating a mass storage and extracting all the relevant data.
Shopping list of evil things
Rubber Ducky: Can emulate a keyboard. Looks innocent and the user can be tricked into inserting it. $45 https://hakshop.com/collections/physical-access/products/usb-rubber-ducky-deluxe
Bash Bunny: $100 https://hakshop.com/products/bash-bunny Can emulate a range of USB devices and run a selection of scripts - it is a miniature USB powered computer with Linux
The need for protecting against rogue USB devices has been anticipated for quite some time already. Here, we present technical artefacts in the area of protecting again USB borne attacks.
Kaspersky Anti-Virus has a security option that aims to prevent the use of compromised USB devices that emulate keyboard behavior. It displays a window when a new USB device has been connected and it asks you to enter a four digit pin from that device. If the device has not a physical keyboard (e.g. a yubikey or a presentation clicker) it is possible to show an on-screen keyboard to let you manually enter the code with a mouse.
In 2007, https://lwn.net/Articles/241980/ the Linux kernel gained the capability of auhorising a device before it is fully bound to a driver. Since 2015, Linux can authorise USB Interfaces separately https://lwn.net/Articles/653319/.
GNOME Shell USB Lock
Using these capabilities, a Summer of Code project created a small prototype for integrating a USB lockdown when the screen is locked: https://github.com/murarugeorgec/USB-checking https://georgemuraruc.wordpress.com/2015/08/25/the-usb-inhibitor/ https://wiki.gnome.org/Outreach/SummerOfCode/2015/Projects/GeorgeMuraru_USBDisable
This work has paved the way to understand how a proctective solution might work. It has, however, not become more mature than a toy project.
USB Guard is a daemon for detecting newly plugged in devices and reacting based on a policy. It is probably the most advanced and most mature software for dealing with dynamic authorisation of devices. Relatively recently they also gained DBus support so it is possible to integrate it with the Desktop.
A KDE frontend exists which shows popups with "hashes" of devices.
Arguably, we should aim for not showing pop-ups, let alone modal one, and never ever pop-ups which enable the user to make a permanent decision without letting the user know how to reset the decision.
GNOME USB Guard
A better integration with the GNOME desktop exists in form of an GNOME Shell icon and GTK popup, called USB Guard GNOME:
Being a tool targeted at the GNOME platform shows. It is more convenient to use and it tries to be clever in certain situations. For example, it locks the screen when a new keyboard is attached and activates the keyboard only once the lockscreen is active.
It currently shows an interactive notification for new devices which you need to click quickly enough. Otherwise the notication disappears into the list of old notification where it is rendered non-interactive. So you will have to re-plug the device in order to have it activated. Also it is unclear whether you can make it less interactive by only having the protection capabilities for when the screen is locked.
ChromeOs USB Guard integration
Some ideas how a first at this problem could look like
We ought to gradually increase the cost of an attack, i.e. we should aim for preventing the trivial attack of just plugging in a malicious device at any time. Once we are able to defend against that, e.g. by only allowing USB devices while the session is active, we might think about malicious devices inserted at a later stage or a device that re-inserts itself after a certain time. The aim of the first step must be to increase the security without changing the existing UX at all. That probably results in a compromise in favour of usability, but that's okay. Once we have added as much security as is possible with the current UX, we implement changes to the UX in order to increase the security further.
1. USB Policies "Always" and "Never" through Privacy settings
In this first case we plan to add an entry to the GNOME Control Center under the Privacy tab. It will allow users to permanently allow or disallow new (?) USB devices from being activated.
The pictures above are mockups of GNOME Control Center rebuilt with the new entry regarding the USB control setting. In this regard we still need to check the capabilities of USBGuard DBus and how we can take advantage of it.
2. "Only when locked" policy
This policy will be a middle ground between "Always" and "Never". In this way the user will be sure that when he lock the screen any malicious USB devices cannot be activated.
We need to find out where to make the decision of allowing or disallowing USB. Is it in GNOME Shell directly or rather in a separate daemon running in the user's session? Then we need to use the USBGuard DBus API to dynamically turn USB on and off. We still need to find out how to actually do it, but we are confident that the API exposes this functionality.
The problem a user could face with a "Only when locked" or "Always" policy is that, for example, he may be left out of the system if his keyboard breaks. In order to avoid that we probably must handle input devices (esp. keyboards) specially, like checking if the new plugged USB is the only input method available.
The three screenshots above are the mockup of this functionality.
3. Handle keyboards and other input devices more gracefully
We need also some research regarding Yubi Keys and similar hardware, what capabilities they expose and if they are seen like a fully featured keyboard. In this case we may require patching of some lower level components (libinput, kernel) to prevent a device from sending keys that they must not be able to send (e.g. 'ctrl' or 'alt')
4. Show new but blocked USB devices on the lockscreen
In the attack scenario, the user comes back to their computer after someone plugged in a malicious devices. We need to let the user know that they have a new device attached that is disabled and what the user can do to have the device activated. Maybe we can show a more prominent widget in the lockscreen.
5. Experiment with the "only when unlocked" policy
In order to assess how well the protection works and how much it impacts working with the system, it should be tested under various workloads. Even better if external test subjects can test the system.
6. Protect against attacks when the session is unlocked
The above methods should all be non-invasive in that they do not require user interaction. Or as little as possible. The situation will change when we try to protect against hardware that is being attached when the session is unlocked. A USB device can come with a timer, after all, to sleep for as long as desired before waking up, so an attacker could make the device sleep for as long as they think that the session will be locked.
Once we cannot easily assume the user's intent regarding the just plugged in device, we will need to find other ways to know about the intents. Because we probably cannot lock the screen every time a new device is plugged in, as GNOME USB Guard does, we need to be smart about what the user is attempting to do. For example, we could introspect the system and notice that a certain class of applications is running and allow appropriate devices. Think webcams for cheese.
Another strategy is to re-identify devices as best as we can, well knowing that the resulting additional protection is marginal, because it is not possible to reliably re-identify a device. But it does arguably increase the protection if the attacker needs to guess the serial number of the target device.
Long story short: We will need to find a way to increase security without compromising too much on usability.