Allow only known usb devices

In this article I'll describe how to protect you 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 to options for Physical Protections:

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

=eudev=

Retrieve information about our USB devices
eudev allows us to create rules to configure devices as they are added or removed from a system, in our case we will allow or disallow USB devices based on their identifying strings. 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 sys-apps/usbutils:

and run:

We can see USB mouse connected on bus 3 and listed as device 2. We will first need to find this device’s port number. To figere out port number run lsusb with -t options:

Also lsusb with -v options expand verbose output, but the format is not convenient for copying and pasting into eudev scripts.

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

The subdirectories we are interested to are in the format (bus number)-(port) or (bus number)-(port).(port). The second one is in case when hub is used the port section of the directory name may be a series of port numbers separated by periods. So pay attention only to follow dirs:

Sysfs, a virtual file system for give information and allow control of devices that the kernel exports. There are one specific settings: "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.

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

All of these "ATTR" attributed can be used in our UDEV rules! You need to add rules to /lib/udev/rules.d/ that will white list 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 file with rules in /lib/udev/rules.d/01-usb.rules to enshure that it is running in the beginning. Pay attention to add all USB hub in the beginning of you rules! All USB hub has ATTR{bDeviceClass}=="09". Also we add more information: ATTR{manufacturer} and ATTR{product} for human readable descriptions..

{{FileBox|filename=/lib/udev/rules.d/01-usb.rules|title=eudev rules for enable only known USB devices| }
 * 1) 20151002
 * 2) GPL-3
 * 3) Enable only known devices

SUBSYSTEM!="usb", GOTO="usb_end" ACTION=="remove", GOTO="usb_end"
 * 1) Skeep not USB
 * 1) Skeep remove actions

SUBSYSTEMS=="usb", ACTION=="add", ATTR{product}=="EHCI Host Controller", ATTR{serial}=="0000:00:1d.7", \ ATTR{idVendor}=="1d6b", ATTR{idProduct}=="0002", ATTR{bDeviceClass}=="09", ATTR{authorized}="1", GOTO="usb_end"
 * 1) Linux Foundation
 * 2) 2.0 root hub

SUBSYSTEMS=="usb", ACTION=="add", ATTR{product}=="UHCI Host Controller", ATTR{serial}=="0000:00:1d.0", \ ATTR{idVendor}=="1d6b", ATTR{idProduct}=="0001", ATTR{bDeviceClass}=="09", ATTR{authorized}="1", GOTO="usb_end"
 * 1) 1.1 root hub

SUBSYSTEMS=="usb", ACTION=="add", ATTR{product}=="UHCI Host Controller", ATTR{serial}=="0000:00:1d.1", \ ATTR{idVendor}=="1d6b", ATTR{idProduct}=="0001", ATTR{bDeviceClass}=="09", ATTR{authorized}="1", GOTO="usb_end"

SUBSYSTEMS=="usb", ACTION=="add", ATTR{product}=="UHCI Host Controller", ATTR{serial}=="0000:00:1d.2", \ ATTR{idVendor}=="1d6b", ATTR{idProduct}=="0001", ATTR{bDeviceClass}=="09", ATTR{authorized}="1", GOTO="usb_end"

SUBSYSTEMS=="usb", ACTION=="add", ATTR{product}=="UHCI Host Controller", ATTR{serial}=="0000:00:1d.3", \ ATTR{idVendor}=="1d6b", ATTR{idProduct}=="0001", ATTR{bDeviceClass}=="09", ATTR{authorized}="1", GOTO="usb_end"

SUBSYSTEMS=="usb", ACTION=="add", ATTR{manufacturer}=="Example", ATTR{product}=="USB Hub", \ ATTR{idVendor}=="5555", ATTR{idProduct}=="5555", ATTR{bDeviceClass}=="09", ATTR{authorized}="1", GOTO="usb_end"
 * 1) Hub

SUBSYSTEMS=="usb", ACTION=="add", ATTR{manufacturer}=="Example", ATTR{product}=="USB Keyboard", \ ATTR{idVendor}=="4444", ATTR{idProduct}=="4444", ATTR{authorized}="1", GOTO="usb_end"

SUBSYSTEMS=="usb", ACTION=="add", ATTR{manufacturer}=="Example", ATTR{product}=="USB Optical Mouse", \ ATTR{configuration}=="HID-compliant MOUSE", ATTR{idVendor}=="2222", ATTR{idProduct}=="2222", ATTR{authorized}="1", GOTO="usb_end"

SUBSYSTEMS=="usb", ACTION=="add", ATTR{manufacturer}=="Example", ATTR{product}=="USB Optical Mouse", \ ATTR{idVendor}=="3333", ATTR{idProduct}=="3333", ATTR{authorized}="1", GOTO="usb_end"

SUBSYSTEMS=="usb", ACTION=="add", ATTR{manufacturer}=="Example", ATTR{product}=="Storage Device 1", ATTR{serial}=="1111111111", \ ATTR{idVendor}=="1111", ATTR{idProduct}=="1111", ATTR{authorized}="1", GOTO="usb_end"

SUBSYSTEMS=="usb", ACTION=="add", ATTR{manufacturer}=="Example", ATTR{product}=="Storage Device 2", ATTR{serial}=="2222222222", \ ATTR{idVendor}=="1111", ATTR{idProduct}=="1111", ATTR{authorized}="1", GOTO="usb_end"

SUBSYSTEMS=="usb", ACTION=="add", ATTR{authorized}="0"
 * 1) Disable all other USB devices

LABEL="usb_end" }}}

Test eudev rules
To test your script you can run the command:

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