14

On a given USB port, I only want to accept USB Mass Storage capabilities, and nothing else. No HID devices, no Bluetooth adapters, no RS232 converters, nothing. Is there a way to do this e.g. using udev? I'm aware that I can write a custom udev rule for including a driver for a given device, or a given port, but can I somehow exclude all other drivers? I'm trying to only allow one class of devices, namely USB Mass Storage; there are a myriad different device models in this class, and I don't know which are going to connect to the port (clients will bring their own, there is no way for me to affect this).

Threats from reprogrammed USB firmware are only going to get worse in the foreseeable future. I'm trying to mitigate them for this use case: I have a computer with internally connected USB peripherals (network card, specialized peripherals, keyboard) and one public-facing USB port, which is only supposed to be used for file transfer. So, I can't blacklist the other USB modules altogether; but I'd like to "sanitize" that particular port, so that plugging in a different device type would do nothing.

The case is physically locked, so that only this one specific USB port is accessible from outside, and meddling with the case or splicing into the keyboard cable should be suspicious enough to trigger physical security response; moreover, I don't expect most of the users to be actively malicious, but I expect the number of unwitting carriers of re-flashed USB drives to increase (as it was with floppy boot sector infections of yore). As far as security goes, it does not really matter whether the user brings the "weaponized" USB disk with malicious intent, or just doesn't know that it's "infected".

I am aware that perfect security is infeasible here, and allowing user to interact with the system in any way is risky - but alas, I need to balance security against usability: the computer needs to be client-usable. Also, I'm not trying to defend against a targetted, determined attacker with this; rather, I'm using this as one of mitigation techniques, so that the system is not low-hanging-fruit.

  • 2
    Um. I'm just learning stuff, so not sure if this may help , but see if this is relevant: "linux-usb.org/FAQ.html" Specifically , scroll to "Why do I only see one device from my multipurpose storage device" question, and there's line " If you do not want to do this for all SCSI devices then you can tell the kernel to scan for a specific device using; echo >/proc/scsi/scsi "scsi add-single-device 0 0 0 1" " – Sergiy Kolodyazhnyy Oct 6 '14 at 8:46
  • 1
    You only want a specific port to be locked to USB Mass Storage? – Kaz Wolfe Oct 6 '14 at 9:41
  • 3
    "With physical access, the battle for security is lost." ~Every Security.SE user ever. – Kaz Wolfe Oct 6 '14 at 10:17
  • 1
    @Piskvor I'm not sure but you might have better luck finding an answer at security.stackexchange.com or one of the other more advanced / professional-oriented sites. – Brian Z Oct 6 '14 at 12:32
  • 2
    Maybe this can help: irongeek.com/… , especially the 3.2 Locking down Linux using UDEV section. – alci Oct 6 '14 at 12:32
16
+250

It seems to work for me in Ubuntu 14.04 with 2 flash keys & android phone as storage and usb network adapter & webcam as other type. (I couldn't test placing a usb hub)

  1. Check USB port (which is a parent device for the plugged device)

    $ udevadm info --name=/dev/sdc --attribute-walk
    
      looking at parent device '/devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2/2-1.2:1.0':
        KERNELS=="2-1.2:1.0"
        SUBSYSTEMS=="usb"
        DRIVERS=="usb-storage"
        ATTRS{bInterfaceClass}=="08"
        ATTRS{bInterfaceSubClass}=="06"
        ATTRS{bInterfaceProtocol}=="50"
        ATTRS{bNumEndpoints}=="02"
        ATTRS{supports_autosuspend}=="1"
        ATTRS{bAlternateSetting}==" 0"
        ATTRS{bInterfaceNumber}=="00"
    
  2. Create udev rule, matching usb port kernel name without usb-storage driver

    /etc/udev/rules.d/90-remove-non-storage.rules

    Allow any device that have storage as 1st interface (Composite devices allowed)

    KERNELS=="2-1.2:1.0", DRIVERS!="usb-storage", RUN+="/bin/sh -c 'echo 1 > /sys/bus/usb/drivers/hub/2-1\:1.0/port2/device/remove'"
    

    Block any device that have a non storage interface (Composite devices denied)

    Actually, Phone gets mounted as modem to /dev/ttyACM0 as KERNELS=="2-1.2:1.1". This will not let phones (composite devices) to be mount only simple storage devices will.

    KERNELS=="2-1.2:1.[0-9]*", DRIVERS!="usb-storage", RUN+="/bin/sh -c 'echo 1 > /sys/bus/usb/drivers/hub/2-1\:1.0/port2/device/remove'"
    

    Block only interfaces that are not storage (Composite devices allowed as storage only)

    After some search about a way to disable only non allowed interfaces. Driver unbinding seems to work. My phone could only be used as storage, It does not create /dev/ttyACM0.

    KERNELS=="2-1.2:1.[0-9]*", DRIVERS!="usb-storage", RUN+="/bin/sh -c 'echo -n %k >/sys%p/driver/unbind'"
    
  3. Reload udev rules

    udevadm control --reload-rules
    

References:

  • Beat me to it... – Kaz Wolfe Oct 6 '14 at 15:52
  • @Whaaaaaat, yep authorized does work too, but remove is a cleaner way as user gonna unplug it anyway. I have checked unmounted drives, they still have usb-storage as driver for a parent node. I agree, there are some cases where usb-storage may not be used. BTW, :) u consume too many comments (2min, 1min), you could edit 1st one (in <5min) – user.dz Oct 6 '14 at 16:41
  • @Whaaaaaat: When I was testing this, the usb-storage driver got loaded right before the block device(s) were created; mounting them was not necessary. – Piskvor Oct 7 '14 at 8:56
  • @Piskvor Did this answer your question? If so, you should mark this as the correct answer and award your bounty. – John Scott Oct 9 '14 at 16:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.