A seemingly innocuous USB flash drive can hide an USB keyboard controller, that once connected to a computer would be able to emulate any series of keystrokes and thus to execute any kind of command.
One way of mitigating this risk is to postulate that all legitimate USB input devices are those already present at boot time—although this may not be true for all users—and consequently to disable any new USB input device appearing after startup.
On GNU/Linux, the following Udev rule may be used to disable USB input devices:
ACTION=="add", SUBSYSTEM=="input", SUBSYSTEMS=="usb", ATTRS{authorized}=="1", \ ENV{PARID}="$id", RUN+="/bin/sh -c 'echo 0 >/sys/bus/usb/devices/$env{PARID}/authorized'"
But this rule must not be applied at startup, otherwise no USB input devices will ever be authorized even if they are present at boot time. 1
So I keep this rule in a file named
/etc/udev/rules.d/99-disable-usb-input.rules.once
. Note the
“.once” extension, which prevents this file from being read by Udev—it
only reads files ending with “.rules”. So this rule won’t be enabled
when Udev performs the initial hardware detection, and input devices
present at startup will be authorized.
Now I just have to rename this file at the end of the startup
sequence, and have Udev reload its rules. This will have no effect on
the already detected devices, but will effectively prevent any
newly-connected USB input devices from being functional. On my Slackware
box, I do that with the following snippet in the
/etc/rc.d/rc.local
script:
if [ -f /etc/udev/rules.d/99-disable-usb-input.rules.once ]; then ln /etc/udev/rules.d/99-disable-usb-input.rules.once /etc/udev/rules.d/99-disable-usb-input.rules /sbin/udevadm control --reload rm /etc/udev/rules.d/99-disable-usb-input.rules fi
If you have some USB input devices that you want to be able
to connect at any time, you may add some special rules allowing
well-identified devices to bypass the disabling rules. Start by
obtaining the idVendor and idProduct of your
device (with udevadm info --attribute-walk
--name=/dev/your_device
), then modify the rules file as
follows:
ACTION=="add", SUBSYSTEM=="input", SUBSYSTEMS=="usb", ATTRS{idVendor}=="xxxx", ATTRS{idProduct}=="yyyy", \ GOTO="authorized_usb_input_devices" ACTION=="add", SUBSYSTEM=="input", SUBSYSTEMS=="usb", ATTRS{authorized}=="1", \ ENV{PARID}="$id", RUN+="/bin/sh -c 'echo 0 >/sys/bus/usb/devices/$env{PARID}/authorized'" LABEL="authorized_usb_input_devices"