mirror of
https://github.com/Qubes-Community/Contents.git
synced 2024-12-22 21:59:26 -05:00
157 lines
7.6 KiB
Markdown
157 lines
7.6 KiB
Markdown
|
|
# USB Hardening
|
|
|
|
Qubes OS provides means to attach [USB devices to a qube](https://www.qubes-os.org/doc/how-to-use-usb-devices/)
|
|
and in general recommends using an [USB qube](https://www.qubes-os.org/doc/usb-qubes/). The Qubes OS
|
|
documentation also highlights the [security implications](https://www.qubes-os.org/doc/device-handling-security/).
|
|
|
|
Nonetheless users may want to
|
|
|
|
- harden their qubes with attached USB devices against USB attacks.
|
|
- harden `dom0` against USB attacks, if they assigned some USB ports to `dom0`, e.g. for USB keyboard or mice
|
|
to avoid the [security pitfalls](https://www.qubes-os.org/doc/device-handling-security/#usb-security) of
|
|
assigning them to an [USB qube](https://www.qubes-os.org/doc/usb-qubes/).
|
|
|
|
[USBGuard](https://usbguard.github.io/) is a tool that can be used for such purposes.
|
|
|
|
## USBGuard
|
|
|
|
### Security Considerations
|
|
|
|
By default the Linux kernel will attempt to recognize plugged in USB devices based on their device ID
|
|
and load the kernel drivers matching that device ID. If e.g. those device drivers have security issues,
|
|
an attacker can exploit those and take control of the qube or in the case of `dom0` the entire system.
|
|
|
|
[USBGuard](https://usbguard.github.io/) uses kernel interfaces to whitelist USB devices based on their
|
|
provided interfaces and device IDs. Keep in mind though that rogue USB devices can easily forge device IDs
|
|
and/or launch a [brute-force attack](https://en.wikipedia.org/wiki/Brute-force_attack) on an unknown
|
|
whitelisted device ID.
|
|
|
|
Rogue devices however cannot exploit interfaces/kernel drivers that are not made available to them due to
|
|
[USBGuard](https://usbguard.github.io/). This is where hardening may make sense.
|
|
|
|
### Installation
|
|
|
|
[USBGuard](https://usbguard.github.io/) should be available from the default repositories of your
|
|
[Qubes templates](https://www.qubes-os.org/doc/templates/).
|
|
|
|
For dom0, you can install it via
|
|
```
|
|
sudo qubes-dom0-update usbguard
|
|
```
|
|
|
|
The [usual security considerations](https://www.qubes-os.org/doc/how-to-install-software-in-dom0/) for
|
|
software installations in `dom0` apply.
|
|
|
|
### `dom0` Example Setup
|
|
|
|
_(The below guide only works with Qubes OS 4.1 or higher.)_
|
|
|
|
The below setup is intended for users with USB ports that are connected to `dom0`. It doesn't whitelist
|
|
any devices (users may want to add their device/interface combinations for convenience), but assumes the
|
|
following:
|
|
|
|
1. All USB devices attached at boot time are allowed, all others rejected.
|
|
2. The user may employ a small script to allow USB devices attached during the next minute or so. Only
|
|
certain reasonable USB device classes (audio, HID, mass storage, hub, smart card) are allowed.
|
|
|
|
#### USBGuard Configuration
|
|
|
|
To achieve that, edit the USBGuard configuration at `/etc/usbguard/usbguard-daemon.conf` to include the
|
|
following lines:
|
|
```
|
|
#reject all devices by default
|
|
ImplicitPolicyTarget=reject
|
|
|
|
#allow all devices that are available at boot time
|
|
PresentDevicePolicy=allow
|
|
PresentControllerPolicy=allow
|
|
```
|
|
|
|
The policy itself at `/etc/usbguard/rules.conf` would have to look as follows:
|
|
```
|
|
############ REJECT #################
|
|
|
|
#only let certain interfaces pass to our default policy and block all others
|
|
#generate via bash: seq 0 255 | while read -r i ; do printf '%.2X:*:* ' "$i" ; done
|
|
#NOTE: reject *:* with-interface none-of { allowed ones } wouldn't work precisely as a malicious device could just add an interface of the allowed types _in addition_ to its unwanted interface types to pass
|
|
#
|
|
#only allowed:
|
|
#01: audio
|
|
#03: HID
|
|
#08: mass storage
|
|
#09: hub
|
|
#0B: smart card
|
|
reject *:* with-interface one-of { 00:*:* 02:*:* 04:*:* 05:*:* 06:*:* 07:*:* 0A:*:* 0C:*:* 0D:*:* 0E:*:* 0F:*:* 10:*:* 11:*:* 12:*:* 13:*:* 14:*:* 15:*:* 16:*:* 17:*:* 18:*:* 19:*:* 1A:*:* 1B:*:* 1C:*:* 1D:*:* 1E:*:* 1F:*:* 20:*:* 21:*:* 22:*:* 23:*:* 24:*:* 25:*:* 26:*:* 27:*:* 28:*:* 29:*:* 2A:*:* 2B:*:* 2C:*:* 2D:*:* 2E:*:* 2F:*:* 30:*:* 31:*:* 32:*:* 33:*:* 34:*:* 35:*:* 36:*:* 37:*:* 38:*:* 39:*:* 3A:*:* 3B:*:* 3C:*:* 3D:*:* 3E:*:* 3F:*:* 40:*:* 41:*:* 42:*:* 43:*:* 44:*:* 45:*:* 46:*:* 47:*:* 48:*:* 49:*:* 4A:*:* 4B:*:* 4C:*:* 4D:*:* 4E:*:* 4F:*:* 50:*:* 51:*:* 52:*:* 53:*:* 54:*:* 55:*:* 56:*:* 57:*:* 58:*:* 59:*:* 5A:*:* 5B:*:* 5C:*:* 5D:*:* 5E:*:* 5F:*:* 60:*:* 61:*:* 62:*:* 63:*:* 64:*:* 65:*:* 66:*:* 67:*:* 68:*:* 69:*:* 6A:*:* 6B:*:* 6C:*:* 6D:*:* 6E:*:* 6F:*:* 70:*:* 71:*:* 72:*:* 73:*:* 74:*:* 75:*:* 76:*:* 77:*:* 78:*:* 79:*:* 7A:*:* 7B:*:* 7C:*:* 7D:*:* 7E:*:* 7F:*:* 80:*:* 81:*:* 82:*:* 83:*:* 84:*:* 85:*:* 86:*:* 87:*:* 88:*:* 89:*:* 8A:*:* 8B:*:* 8C:*:* 8D:*:* 8E:*:* 8F:*:* 90:*:* 91:*:* 92:*:* 93:*:* 94:*:* 95:*:* 96:*:* 97:*:* 98:*:* 99:*:* 9A:*:* 9B:*:* 9C:*:* 9D:*:* 9E:*:* 9F:*:* A0:*:* A1:*:* A2:*:* A3:*:* A4:*:* A5:*:* A6:*:* A7:*:* A8:*:* A9:*:* AA:*:* AB:*:* AC:*:* AD:*:* AE:*:* AF:*:* B0:*:* B1:*:* B2:*:* B3:*:* B4:*:* B5:*:* B6:*:* B7:*:* B8:*:* B9:*:* BA:*:* BB:*:* BC:*:* BD:*:* BE:*:* BF:*:* C0:*:* C1:*:* C2:*:* C3:*:* C4:*:* C5:*:* C6:*:* C7:*:* C8:*:* C9:*:* CA:*:* CB:*:* CC:*:* CD:*:* CE:*:* CF:*:* D0:*:* D1:*:* D2:*:* D3:*:* D4:*:* D5:*:* D6:*:* D7:*:* D8:*:* D9:*:* DA:*:* DB:*:* DC:*:* DD:*:* DE:*:* DF:*:* E0:*:* E1:*:* E2:*:* E3:*:* E4:*:* E5:*:* E6:*:* E7:*:* E8:*:* E9:*:* EA:*:* EB:*:* EC:*:* ED:*:* EE:*:* EF:*:* F0:*:* F1:*:* F2:*:* F3:*:* F4:*:* F5:*:* F6:*:* F7:*:* F8:*:* F9:*:* FA:*:* FB:*:* FC:*:* FD:*:* FE:*:* FF:*:* }
|
|
|
|
############# ALLOW ################
|
|
|
|
# You may want to add your devices here for convenience, but it's not absolutely necessary if you use the provided script to temporarily allow new devices.
|
|
|
|
#NOTE: the one-ofs are workarounds for https://github.com/USBGuard/usbguard/issues/207
|
|
# Since we filter out everything else above, one-of should be fine.
|
|
|
|
#USB hubs (some internal)
|
|
#allow id xxxx:xxxx with-interface one-of { 09:*:* }
|
|
|
|
#mouse & keyboard
|
|
#allow id xxxx:xxxx with-interface one-of { 03:*:* }
|
|
|
|
#external sound card
|
|
#allow id xxxx:xxxx with-interface one-of { 01:*:* }
|
|
|
|
#hard disks
|
|
#allow id xxxx:xxxx with-interface one-of { 08:*:* }
|
|
|
|
#smart cards
|
|
#allow id xxxx:xxxx with-interface one-of { 0B:*:* }
|
|
|
|
########### DEFAULT #################
|
|
|
|
#Everything connected during service startup will otherwise be allowed in this configuration.
|
|
#Everything connected later will be rejected.
|
|
```
|
|
|
|
Please note that misconfigurations to the `usbguard` configuration may make the respective USB devices
|
|
temporarily unusable on your host. The log file available at `/var/log/usbguard/usbguard.log` may help
|
|
to investigate issues.
|
|
|
|
At the end of the configuration, you may have to restart the service via `systemctl restart usbguard`.
|
|
Also make sure that it is enabled at boot time via `systemctl enable usbguard`.
|
|
|
|
#### Script to temporarily allow new devices
|
|
|
|
To temporarily allow new devices for 60 seconds, you can e.g. use the following script:
|
|
|
|
```bash
|
|
#!/bin/bash
|
|
#
|
|
# Temporarily allow new USB devices.
|
|
#
|
|
# Assumes ImplicitPolicyTarget=reject in the default configuration.
|
|
#
|
|
# Related:
|
|
# https://github.com/USBGuard/usbguard/issues/367
|
|
# https://github.com/USBGuard/usbguard/issues/436
|
|
|
|
function error {
|
|
local msg="$1"
|
|
notify-send -u critical -t 90000 "usbguard ERROR" "$msg"
|
|
>&2 echo "ERROR: $1"
|
|
exit 1
|
|
}
|
|
|
|
[ $EUID -eq 0 ] || error "This script must be run as root."
|
|
|
|
# This works from usbguard 0.75 on (only Qubes 4.1+):
|
|
policy="$(usbguard get-parameter ImplicitPolicyTarget)" || error "Failed to retrieve the current usbguard policy."
|
|
[[ "$policy" == "allow" ]] && error "Already allowing everything. No need to run."
|
|
usbguard set-parameter ImplicitPolicyTarget allow || error "Failed to execute usbguard."
|
|
notify-send -t 60000 "usbguard" "Allowing all..."
|
|
|
|
sleep 60
|
|
|
|
usbguard set-parameter ImplicitPolicyTarget "$policy" || error "Failed to set usbguard back to its old policy!"
|
|
notify-send -t 15000 "usbguard" "${policy}ing again."
|
|
```
|