Allow only known usb devices

In this article I'll describe how to protect your GNU/Linux box against alien USB devices. So we configure GNU/Linux to accept only known USB devices.

=Kernel protection=

In kernel "sys-kernel/hardened-sources" we have two options for Physical Protections:

It is very good choice for servers in datacenter and server's rooms. But at reboot it is still vulnerable! Also it does not give the flexibility needed on workstations when we want to connect USB devices during run time. So let's write eudev rules to allow only known USB devices in the system.

=eudev=

eudev allows us to create rules to configure devices as they are added or removed from a system, in our case we will allow and disallow USB devices based on their identifying strings.

Retrieve information about our USB devices
The first thing that needs to be done is to collect identifying strings that can be used to white list our USB devices.

lsusb
How to obtain more information about connected USB devices? Install package usbutils:

and run:

We can see USB Optical Mouse connected on bus 3 and listed as device 2. We need first to find this device’s port number. To figure out port numbers run lsusb with option -t:

Now we can see that USB Optical Mouse connected on bus 3 and listed as device 2 really connected at port 1 of USB bus 3! Also lsusb with option -v expand verbose output, but the format is not convenient for copying and pasting into eudev rules.

Sysfs
Information about attached USB devices can be obtained through Sysfs:

The subdirectories we are interested in are in the format bus_number-port or bus_number-port.port. The second one is in case hubs are used, then port section of the directory name may be a series of port numbers separated by periods. So pay attention only to follow dirs:

usb1 usb2  usb3  usb4  usb5 is a Linux root hub, don't forgot add rules for them!!!

Sysfs is a virtual file system that gives information and allows the control of devices which the kernel exports. There is one specific setting: authorized. All USB devices should have an authorized option which controls whether or not the device can communicate with the system. For example, if we wished to see if the device in port 1 of the 3 USB bus is active we could use the following command:

The 1 in the output tells us the device is authorized, 0 would mean not authorized. So we can allow USB devices by running:

And disallow:

But it is not convenient too.

udevadm
To retrieve information like the serial number, vendor and product ID and manufacturer’s name of our device connected to port 1 on 3 USB bus, you can run the following command:

All of these "ATTR" attributes can be used in our eudev rules. You need to add rules to /lib/udev/rules.d/ that will whitelist only the given devices, and blacklist all the rest.

Writing eudev rules
Now we can start writing eudev rules to enable/disable USB devices. Create a file with rules in /lib/udev/rules.d/01-usb.rules to ensure that it is running in the beginning. Pay attention to add all USB hubs at the start of your rules. All USB hubs have ATTR{bDeviceClass}=="09". Also we add more information: ATTR{manufacturer} and ATTR{product} for human readable descriptions.

To authorize the device set ATTR{authorized}="1", to block it, set ATTR{authorized}="0"

Smartphones, E-book, and so on..
Some multifunction modern devices like smartphones, ebook, and so on has many operation modes. It can operate as USB storage device, USB camera, USB modem, USB network device, ... So when we write rule for such devices we must add one rule for each operation modes! Reattach device, switch different operation modes and see deference in output:

It can change his serial number or ATTR{idProduct}=="000a" attribute! So eudev rules for such device look like:

Or

Test eudev rules
To test your script run the following command:

It will not actually apply the changes, it only shows which conditional statements are applied when a certain device is inserted.