Abstract
| Goal |
Protect systems from rogue USB device access with USBGuard. |
| Sections |
|
| Lab |
|
USBGuard is a software framework that protects your systems against rogue USB devices by implementing basic allowlist and blocklist capabilities based on device attributes. The Linux kernel authorizes USB devices by enforcing the settings that USBGuard configures. For example, you can define what types of USB devices are allowed and how a USB device can interact with your system.
The USBGuard framework provides the following components:
A system service component with an inter-process communication (IPC) interface for dynamic interaction and policy enforcement.
A command-line interface to interact with a running USBGuard instance.
A rule language for writing USB device authorization policies.
A C++ API for interacting with the system service component that is implemented in a shared library.
The usbguard package provides the usbguard service, which works with the kernel to enforce the USBGuard policies, and provides the usbguard command to manage the USBGuard policies.
USBGuard provides its own SELinux policy, which is confined under the usbguard_t domain.
Run the following command to install the usbguard package:
[root@host ~]# dnf install usbguardUse the following optional packages for managing USB devices:
usbutils
The usbutils package provides the lsusb command to display information about the USB buses in the system and connected devices.
udisks2
The udisks2 package provides interfaces to count and perform operations on disks and storage devices.
The udisks2 package provides the udisksctl tool, which interacts with the udisksd daemon.
The udisksctl command status option provides high-level information about disk drives and block devices.
Use the following command to install the optional supporting packages:
[root@host ~]$ dnf install usbutils udisks2Start the usbguard daemon:
[root@host ~]# systemctl enable --now usbguard.serviceThe USBGuard daemon determines whether to allow a USB device based on a policy that a set of rules defines. When a USB device is inserted into the system, the daemon scans the existing rules sequentially. When a matching rule is found, the daemon allows, blocks, or rejects the device based on the rule target. If no matching rule is found, then the decision is based on an implicit default target. This implicit default is to block the device until you decide to allow it.
Rule Targets
The rule target determines whether the system allows you to use a USB device that matches that rule. The following rule targets help to manage the authorization of a USB device:
Allow the device. The device and its interfaces are allowed to communicate with the system.
Disallow the device. The device is visible to the system but remains in a blocked state until it is allowed.
Disallow and remove the device from the system. The device must be reinserted to become visible to the system again.
The usbguard command provides a CLI to the USBGuard daemon.
List all USB devices that the USBGuard daemon recognizes:
[root@host ~]# usbguard list-devicesAllow a device that the device number identifies to interact with the system:
[root@host ~]# usbguard allow-device 1Disallow a device that the device number identifies:
[root@host ~]# usbguard block-device 2Disallow and remove a device that the device number identifies:
[root@host ~]# usbguard reject-device 2List the rule set (policy) that the usbguard daemon uses:
[root@host ~]# usbguard list-rulesGenerate a rule set (policy) that allows the currently connected USB devices:
[root@host ~]# usbguard generate-policy > /etc/usbguard/rules.confRemove a rule that is identified by the rule number:
[root@host ~]# usbguard remove-rule 3Persistent USBGuard rules are stored in the /etc/usbguard/rules.conf file.
The initial file that is installed on the system is empty, and the root user owns it.
Use the usbguard generate-policy command to create a persistent initial rule set that allows the currently connected USB devices.
[root@host ~]# usbguard generate-policy > /etc/usbguard/rules.confAfter generating the policy, you must start or restart the usbguard service to apply the changes from the /etc/usbguard/rules.conf file:
[root@host ~]# systemctl enable --now usbguardUse the following command to inspect the contents of the rules.conf file:
[root@host ~]#usbguard list-rules4:allowid1d6b:0001serial"0000:00:01.2"name"UHCI Host Controller"hash"FRDEjz7OhdJbNjmJ8zityiNX/LuO+ovKC07I0bOFjao="parent-hash"9+Zsfvo9IR/AEQ/Fn4mzdoPGk0rqpjku6uErfS09K4c="with-interface09:00:00 with-connect-type ""
Rule Composition
Using the fourth rule in the list (rule 4) as an example, the components are as follows:
4
This field represents the rule number.
allow
This field designates the rule target (policy) that is applied to the device.
id
The USB device ID is a colon-delimited pair in the vendor_id:product_id form.
For all USB devices, the manufacturer assigns this ID, and it must uniquely identify a USB product.
Both vendor_id and product_id values are 16-bit numbers that are represented in hexadecimal base.
You can use an asterisk character to match either any device ID *:* or any product ID from a specific vendor, for example, 1234:*.
serial
This field shows the USB serial device attribute.
name
This field shows the USB device name attribute.
hash
The hash field contains a hash that is computed from the device attribute values and the USB descriptor data.
USBGuard computes the hash for every device.
The hash attribute is the most specific value to identify a device.
parent-hash
The parent-hash field contains a hash value that is computed similarly to the one in the hash field, but for the parent USB device of the USB device.
For example, the parent USB device might be a USB hub that the device is plugged into.
with-interface
This field shows the interface that the USB device provides.
Dynamically allowing a USB device is useful for granting temporary access to a device.
If a USB device is attached to the system and the default policy does not allow access to the system, then the device is assigned the block rule target.
Use the usbguard command to list and modify the authorization of the devices.
[root@host ~]#usbguard list-devices: allow id 1d6b:0001 serial "0000:00:01.2" name "UHCI Host Controller" hash "FRDEjz7OhdJbNjmJ8zityiNX/LuO+ovKC07I0bOFjao=" parent-hash "9+Zsfvo9IR/AEQ/Fn4mzdoPGk0rqpjku6uErfS09K4c=" via-port "usb1" with-interface 09:00:00 with-connect-type ""1: block id 0627:0001 serial "42" name "QEMU USB Tablet" hash "V2g2ylTpBl8oDeqJ8qb2rZNeKY0z38+qm2Z4bkSK+20=" parent-hash "FRDEjz7OhdJbNjmJ8zityiNX/LuO+ovKC07I0bOFjao=" via-port "1-1" with-interface 03:00:00 with-connect-type "unknown"2
Use the usbguard command to dynamically allow the USB device with the device number:2
[root@host ~]# usbguard allow-device 2List the devices to verify that the device is now allowed to interact with the system:
[root@host ~]#usbguard list-devices: allow id 1d6b:0001 serial "0000:00:01.2" name "UHCI Host Controller" hash "FRDEjz7OhdJbNjmJ8zityiNX/LuO+ovKC07I0bOFjao=" parent-hash "9+Zsfvo9IR/AEQ/Fn4mzdoPGk0rqpjku6uErfS09K4c=" via-port "usb1" with-interface 09:00:00 with-connect-type ""1: allow id 0627:0001 serial "42" name "QEMU USB Tablet" hash "V2g2ylTpBl8oDeqJ8qb2rZNeKY0z38+qm2Z4bkSK+20=" parent-hash "FRDEjz7OhdJbNjmJ8zityiNX/LuO+ovKC07I0bOFjao=" via-port "1-1" with-interface 03:00:00 with-connect-type "unknown"2
The usbguard command does not add the rule target in the /etc/usbguard/rules.conf file, and the changes do not persist after reboot.
[root@host ~]# usbguard list-rules
1: allow id 1d6b:0001 serial "0000:00:01.2" name "UHCI Host Controller" hash "FRDEjz7OhdJbNjmJ8zityiNX/LuO+ovKC07I0bOFjao=" parent-hash "9+Zsfvo9IR/AEQ/Fn4mzdoPGk0rqpjku6uErfS09K4c=" with-interface 09:00:00 with-connect-type ""If you dynamically allow a USB device to interact with the system by setting a temporary rule, then you might want that rule to persist after reboots to permanently allow the device.
The usbguard allow-device command -p option allows a USB device that is identified by the device number to persistently interact with the system across reboots.
The -p option gives persistent authorization by adding the allow rule target to the policy in the /etc/usbguard/rules.conf file.
[root@host ~]#usbguard list-devices1: allow id 1d6b:0001 serial "0000:00:01.2" name "UHCI Host Controller" hash "FRDEjz7OhdJbNjmJ8zityiNX/LuO+ovKC07I0bOFjao=" parent-hash "9+Zsfvo9IR/AEQ/Fn4mzdoPGk0rqpjku6uErfS09K4c=" via-port "usb1" with-interface 09:00:00 with-connect-type ""2: allow id 0627:0001 serial "42" name "QEMU USB Tablet" hash "V2g2ylTpBl8oDeqJ8qb2rZNeKY0z38+qm2Z4bkSK+20=" parent-hash "FRDEjz7OhdJbNjmJ8zityiNX/LuO+ovKC07I0bOFjao=" via-port "1-1" with-interface 03:00:00 with-connect-type "unknown"
Use the following command to add a persistent allow rule target for the device number:2
[root@host ~]# usbguard allow-device -p 2After adding a rule to the /etc/usbguard/rules.conf file, you must restart the usbguard service to apply the changes:
[root@host ~]# systemctl restart usbguard.serviceThe usbguard list-rules command shows the USB with the device ID in the output.
The output confirms an entry in the 0627:0001/etc/usbguard/rules.conf file, which means that the changes will persist across reboots.
[root@host ~]# usbguard list-rules1: allow id 1d6b:0001 serial "0000:00:01.2" name "UHCI Host Controller" hash "FRDEjz7OhdJbNjmJ8zityiNX/LuO+ovKC07I0bOFjao=" parent-hash "9+Zsfvo9IR/AEQ/Fn4mzdoPGk0rqpjku6uErfS09K4c=" with-interface 09:00:00 with-connect-type ""2: allow id0627:0001serial "42" name "QEMU USB Tablet" hash "V2g2ylTpBl8oDeqJ8qb2rZNeKY0z38+qm2Z4bkSK+20=" parent-hash "FRDEjz7OhdJbNjmJ8zityiNX/LuO+ovKC07I0bOFjao=" with-interface 03:00:00 with-connect-type "unknown"
To prevent devices from interacting with the system, you can block or reject the device. When you block a device, the system can see it but not use it. When you reject a device, the system cannot see or use the device.
Use the usbguard block-device command with the device number to set the block rule target:
[root@host ~]# usbguard block-device 2Use the -p option to block a device persistently:
[root@host ~]# usbguard block-device -p 2Use the usbguard reject-device command with the device number to set the reject rule target:
[root@host ~]# usbguard reject-device 2Use the following command to persistently reject a device:
[root@host ~]# usbguard reject-device -p 2The /etc/usbguard/usbguard-daemon.conf file is the default system configuration file.
The USBGuard daemon loads this file after it parses the command-line options to configure the runtime parameters of the USBGuard daemon.
You can override the default file with another file by using the usbguard-daemon command -c option.
Selected USBGuard Configuration Options:
The usbguard daemon loads the policy rule set from this file, and also writes new rules that are received through the IPC interface to this file.
The target value determines how the USBGuard daemon treats the devices that do not match any rule in the policy.
The default value is block.
The value can be the allow, block, or reject rule target.
The value determines the policy for treating devices that are already connected when the daemon starts:
allow: This policy allows every connected device.
block: This policy disallows every connected device.
reject: This policy removes every connected device.
keep: This policy synchronizes the internal state and keeps the device's current state.
apply-policy: This policy evaluates the rule set for every connected device.
The value determines the policy for treating USB controllers that are already connected when the daemon starts.
This policy also accepts the values that are available in the PresentDevicePolicy policy.
You can provide a space-delimited list of user names that the daemon accepts IPC connections for.
You can provide a space-delimited list of group names that the daemon accepts IPC connections for.
You can provide a path to a directory with the IPC access control files.
The usbguard daemon uses the /etc/usbguard/usbguard-daemon.conf configuration file to load rules from the /etc/usbguard/rules.conf file, and allows only users from the usbguard group to use the IPC interface.
The following example allows the wheel group to use the IPC interface:
IPCAllowedGroups=wheel
The usbguard add-user and usbguard remove-user commands specify the IPC Access Control List (ACL).
In the following example, the usbguard add-user command allows users from the usbguard group to modify the USB device authorization state, list USB devices, listen to exception events, and list the USB authorization policy:
[root@host ~]#usbguard add-user -g usbguard \>--devices=modify,list,listen --policy=list --exceptions=listen
In Red Hat Enterprise Linux, the access to this interface is by default limited to the root user.
You must set either the IPCAccessControlFiles option (recommended) or set the IPCAllowedUsers and IPCAllowedGroups options to limit access to the IPC interface.
Leaving the ACL unconfigured exposes the IPC interface to all local users, which means that a user could manipulate the authorization state of USB devices and modify the USBGuard policy.
If the devices can be examined and identified accurately, then you can implement policies to allow or block devices.
If accurate identification of the device is not possible, then you can add more flexible rules to the /etc/usbguard/rules.conf file based on device characteristics.
Blocking a device based on its USB class or characteristics might not be strict enough for some organizations.
In this case, you might reject devices based on their USB classes or sets of characteristics.
The following example allows a specific YubiKey device to be connected via a specific port. The policy is written to reject everything else on that port.
allow 1050:0011 name "Yubico Yubikey II" serial "0001234567" via-port "1-2" hash "044b5e168d40ee0245478416caf3d998" reject via-port "1-2"
In the previous example, you could use just the hash to match the device. However, by using the name and serial attributes, you can quickly assign rules to specific devices without computing the hash. That said, the hash is the most specific value for identifying a device in USBGuard, so it is the best attribute to use for a rule to match only one device.
You can add a policy in the /etc/usbguard/rules.conf file to allow USB mass storage devices (USB flash disks) and to block everything else.
This policy blocks any device that has capabilities in addition to mass storage, such as a hidden keyboard. Devices with a single mass storage interface are allowed to interact with the operating system.
In the following output, the interface type represents a USB interface, and must be formatted as three 8-bit colon-delimited hexadecimal numbers:
{ interface class:subclass:protocol }The policy consists of a single rule:
allow with-interface equals { 08:*:* }In this policy, the blocking is implicit because a block rule was not included. Implicit blocking is useful to desktop users because a desktop applet that is listening to USBGuard events can ask the user for a decision if an implicit target was selected for a device.
A USB flash disk that implements a keyboard or a network interface is suspicious. The following set of rules forms a policy that allows USB flash disks and explicitly rejects devices with additional suspicious interfaces.
allow with-interface equals { 08:*:* }
reject with-interface all-of { 08:*:* 03:00:* }
reject with-interface all-of { 08:*:* 03:01:* }
reject with-interface all-of { 08:*:* e0:*:* }
reject with-interface all-of { 08:*:* 02:*:* }The policy rejects all USB flash disk devices with an interface from the Human Interface Devices (HID), communications, and wireless classes. Red Hat recommends blocking devices by default and explicitly allowing devices that are needed. This policy assumes that blocking is the default approach. Red Hat also recommends rejecting sets of devices that are considered to be bad, such as flash devices that include a suspicious keyboard interface.
usbguard(1), usbguard-daemon(8), usbguard-daemon.conf(5), and usbguard-rules.conf(5) man pages.
For more information, refer to the Protecting Systems Against Intrusive USB Devices chapter in the Red Hat Enterprise Linux 9 Security Hardening guide at https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/9/html/security_hardening/protecting-systems-against-intrusive-usb-devices_security-hardening