Bookmark this page

Chapter 4. Restricting USB Device Access

Abstract

Goal Protect systems from rogue USB device access with USBGuard.
Objectives
  • Configure and use USBGuard in order to selectively control USB device access.

Sections

Controlling USB access with USBGuard (and Guided Exercise)

Lab

Restricting USB Device Access

Controlling USB Access with USBGuard

Objectives

After completing this section, students should be able to configure and use USBGuard to selectively control USB device access.

Introduction to USBGuard

USBGuard is a software framework that protects your systems against rogue USB devices by implementing basic whitelisting and blacklisting capabilities based on device attributes. The Linux kernel's USB device authorization system is used to enforce the settings configured by USBGuard. This allows you to control access to USB devices. For example, you can define what kind of USB devices are authorized and how a USB device may interact with your system.

The USBGuard framework provides the following components:

  • The daemon component, which has an interprocess communication (IPC) interface for dynamic interaction and policy enforcement.

  • The command-line interface, used to interact with a running USBGuard instance.

  • The rule language, used to write USB device authorization policies.

  • The C++ API, used to interact with the daemon component, implemented in a shared library.

Controlling USB access with USBGuard

Installing USBGuard

The usbguard RPM package provides usbguard-daemon, which works with the kernel to enforce the USBGuard policies, and the usbguard command, which you use to manage the USBGuard policies.

Other optional packages that support USB device management include:

usbutils

Provides the lsusb utility for displaying information about USB buses in the system and devices connected to them.

udisks2

Provides interfaces to enumerate and perform operations on disks and storage devices. For the purpose of this chapter the udisks2 package provides the udisksctl command-line tool which interacts with the udisksd daemon process. When the udisksctl tool is used with the status command it provides high-level information about disk drives and block devices.

To install usbguard, run the following command:

[user@demo ~]$ sudo yum install usbguard

To install optional supporting packages, usbutils and udisk2, run the following command:

[user@demo ~]$ sudo yum install usbutils udisks2

Using USBGuard

The usbguard daemon determines whether or not to authorize a USB device based on a policy defined by a set of rules. When a USB device is inserted into the system, the daemon scans the existing rules sequentially. When a matching rule is found, it either authorizes (allows), does not authorize (blocks), or removes (rejects) the device, based on the rule target. If no matching rule is found, the decision is based on an implicit default target. This implicit default is to block the device until a decision is made by the user.

Rule Targets

The target of a rule specifies whether the device will be authorized for use or not. Three types of target are recognized:

allow

Authorize the device. The device and its interfaces will be allowed to communicate with the system.

block

Do not authorize the device. The device is visible to the system but will remain in a blocked state until it is authorized.

reject

Deauthorize and remove the device from the system. The device will have to be re-inserted to become visible to the system again.

Using the USBGuard Command-line Interface (CLI)

The usbguard command provides a CLI to the usbguard daemon instance and provides a tool for generating initial USBGuard policies.

Common usbguard Subcommands

list-devices

List all USB devices recognized by the USBGuard daemon.

allow-device id

Authorize a device identified by the device id to interact with the system.

block-device id

Deauthorize a device identified by the device id.

reject-device id

Deauthorize and remove a device identified by the device id.

list-rules

List the rule set (policy) used by the USBGuard daemon.

append-rule rule

Append the new rule after a rule with the specified rule id.

remove-rule id

Remove a rule identified by the rule id from the rule set.

generate-policy

Generate a rule set (policy) which authorizes the currently connected USB devices.

Creating an Initial Rule Set

Persistent USBGuard rules are stored in the /etc/usbguard/rules.conf file. The initial file installed on the system is empty and owned by the root user. Use the usbguard generate-policy command to create a persistent initial rule set that authorizes the currently connected USB devices. After generating the policy you must start or restart the usbguard service to allow it to process the contents of the /etc/usbguard/rules.conf file.

[root@demo ~]# usbguard generate-policy > /etc/usbguard/rules.conf
[root@demo ~]# systemctl restart usbguard

Inspect the contents of the rules.conf file:

[root@demo ~]# usbguard list-rules
1: allow id 1d6b:0002 serial "0000:00:04.7" name "EHCI Host Controller" hash "CsKOZ6IY8v3eojsc1fqKDW84V+MMhD6HsjjojcZBjSg=" parent-hash "qiR4Ubbd7AIXLCz201hJYzaO9KIrOvqqRgqs2vM2NOY=" with-interface 09:00:00
2: allow id 1d6b:0001 serial "0000:00:04.0" name "UHCI Host Controller" hash "sKXn6PthDDlGgdxZHdnlUQ9DROkH/YSojkBlfpcnsaU=" parent-hash "VC8ZB6FZ51WMN42QA3CqGvK9+eLDu4jpdgzSwLFn+fs=" with-interface 09:00:00
3: allow id 1d6b:0001 serial "0000:00:04.1" name "UHCI Host Controller" hash "6t6CPSS/v2EqQwsw6CMq8DVfOhgUGO2f+bEBX7R2yz0=" parent-hash "0JRYS5mysCKe92s8So5WC7cbttP3haCBtScjU64BJs0=" with-interface 09:00:00
4: allow id 1d6b:0001 serial "0000:00:04.2" name "UHCI Host Controller" hash "BSaNQWADaBI31jUqbck0N56uRuh3uVT1Vk4rdoD0ghs=" parent-hash "prVi21GR+cpMC0ykIE8H9TC9QoaAkFrbmw2PLcWNGkw=" with-interface 09:00:00

Rule Composition

Using the first rule in the list (rule 1) the components are as follows:

1:

Represents the rule number.

allow

Designates the rule target (policy).

id 1d6b:0001

The usb-device-id is a colon delimited pair in the form vendor_id:product_id. All USB devices have this ID assigned by the manufacturer and it should uniquely identify a USB product. Both vendor_id and product_id are 16-bit numbers represented in hexadecimal base. It is possible to use an asterisk character to match either any device ID *:* or any product ID from a specific vendor, for example, 1234:*.

serial "0000:00:04.2"

Matches the USB iSerial device attribute.

name "UHCI Host Controller"

Matches the USB device name attribute.

hash and parent-hash

Matches a hash computed from the device attribute values and the USB descriptor data. The hash is computed for every device by USBGuard. Using the hash attribute is the most specific value you can use to identify a device.

with-interface 09:00:00

Match an interface type that the USB device provides.

Dynamically Authorize a Device to Interact with the System

If a USB device is attached to the system after the default policy is generated it is not authorized to access the system and is assigned a block rule target. Use the usbguard list-devices command to list all devices and their attributes as recognized by the usbguard daemon.

[root@demo ~]# usbguard list-devices
1: allow id 1d6b:0002 serial "0000:00:06.7" name "EHCI Host Controller" hash "JDOb0BiktYs2ct3mSQKopnOOV2h9MGYADwhT+oUtF2s=" parent-hash "4PHGcaDKWtPjKDwYpIRG722cB9SlGz9l9Iea93+Gt9c=" via-port "usb1" with-interface 09:00:00
...
6: block id 1b1c:1ab1 serial "000024937962" name "Voyager" hash "CrXgiaWIf2bZAU+5WkzOE7y0rdSO82XMzubn7HDb95Q=" parent-hash "JDOb0BiktYs2ct3mSQKopnOOV2h9MGYADwhT+oUtF2s=" via-port "1-3" with-interface 08:06:50

Use the usbguard allow-device 6 command to dynamically authorize the USB device with device number 6 from the output of the previous usbguard list-devices command:

[root@demo ~]# usbguard allow-device 6

List the devices to verify that the device is now allowed to interact with the system:

[root@demo ~]# usbguard list-devices
1: allow id 1d6b:0002 serial "0000:00:06.7" name "EHCI Host Controller" hash "JDOb0BiktYs2ct3mSQKopnOOV2h9MGYADwhT+oUtF2s=" parent-hash "4PHGcaDKWtPjKDwYpIRG722cB9SlGz9l9Iea93+Gt9c=" via-port "usb1" with-interface 09:00:00
...
6: allow id 1b1c:1ab1 serial "000024937962" name "Voyager" hash "CrXgiaWIf2bZAU+5WkzOE7y0rdSO82XMzubn7HDb95Q=" parent-hash "JDOb0BiktYs2ct3mSQKopnOOV2h9MGYADwhT+oUtF2s=" via-port "1-3" with-interface 08:06:50

Running the usbguard list-rules command will not include the USB device with id 1b1c:1ab1 because it was dynamically added and therefore was not entered into the /etc/usbguard/rules.conf file and will not persist across reboots. Dynamically allowing a USB device is useful when you only want to grant temporary access for a particular device.

[root@demo ~]# usbguard list-rules
1: allow id 1d6b:0002 serial "0000:00:04.7" name "EHCI Host Controller" hash "CsKOZ6IY8v3eojsc1fqKDW84V+MMhD6HsjjojcZBjSg=" parent-hash "qiR4Ubbd7AIXLCz201hJYzaO9KIrOvqqRgqs2vM2NOY=" with-interface 09:00:00
2: allow id 1d6b:0001 serial "0000:00:04.0" name "UHCI Host Controller" hash "sKXn6PthDDlGgdxZHdnlUQ9DROkH/YSojkBlfpcnsaU=" parent-hash "VC8ZB6FZ51WMN42QA3CqGvK9+eLDu4jpdgzSwLFn+fs=" with-interface 09:00:00
3: allow id 1d6b:0001 serial "0000:00:04.1" name "UHCI Host Controller" hash "6t6CPSS/v2EqQwsw6CMq8DVfOhgUGO2f+bEBX7R2yz0=" parent-hash "0JRYS5mysCKe92s8So5WC7cbttP3haCBtScjU64BJs0=" with-interface 09:00:00
4: allow id 1d6b:0001 serial "0000:00:04.2" name "UHCI Host Controller" hash "BSaNQWADaBI31jUqbck0N56uRuh3uVT1Vk4rdoD0ghs=" parent-hash "prVi21GR+cpMC0ykIE8H9TC9QoaAkFrbmw2PLcWNGkw=" with-interface 09:00:00

Authorizing a Device to Persistently Interact with the System

The usbguard allow-device -p 6 command authorizes a USB device identified by the device number 6 to interact with the system. The -p option makes the authorization persistent by adding the allow rule target to the policy in the /etc/usbguard/rules.conf file.

[root@demo ~]# usbguard list-devices
1: allow id 1d6b:0002 serial "0000:00:06.7" name "EHCI Host Controller" hash "JDOb0BiktYs2ct3mSQKopnOOV2h9MGYADwhT+oUtF2s=" parent-hash "4PHGcaDKWtPjKDwYpIRG722cB9SlGz9l9Iea93+Gt9c=" via-port "usb1" with-interface 09:00:00
...
6: block id 1b1c:1ab1 serial "000024937962" name "Voyager" hash "CrXgiaWIf2bZAU+5WkzOE7y0rdSO82XMzubn7HDb95Q=" parent-hash "JDOb0BiktYs2ct3mSQKopnOOV2h9MGYADwhT+oUtF2s=" via-port "1-3" with-interface 08:06:50

Use the following command to add a persistent allow rule target for device number 6 from the previous listing to the /etc/usbguard/rules.conf file:

[root@demo ~]# usbguard allow-device -p 6

When a rule is added to the /etc/usbguard/rules.conf file, you must restart the usbguard service to ensure that the USBGuard daemon scans the file and loads any changed entries.

[root@demo ~]# systemctl restart usbguard

Running the usbguard list-rules command will include the USB device with id 1b1c:1ab1 as part of its output which confirms that it has an entry in the /etc/usbguard/rules.conf file and will persist across reboots. The rule number may be different depending on your system.

[root@demo ~]# usbguard list-rules
1: allow id 1d6b:0002 serial "0000:00:04.7" name "EHCI Host Controller" hash "CsKOZ6IY8v3eojsc1fqKDW84V+MMhD6HsjjojcZBjSg=" parent-hash "qiR4Ubbd7AIXLCz201hJYzaO9KIrOvqqRgqs2vM2NOY=" with-interface 09:00:00
2: allow id 1d6b:0001 serial "0000:00:04.0" name "UHCI Host Controller" hash "sKXn6PthDDlGgdxZHdnlUQ9DROkH/YSojkBlfpcnsaU=" parent-hash "VC8ZB6FZ51WMN42QA3CqGvK9+eLDu4jpdgzSwLFn+fs=" with-interface 09:00:00
3: allow id 1d6b:0001 serial "0000:00:04.1" name "UHCI Host Controller" hash "6t6CPSS/v2EqQwsw6CMq8DVfOhgUGO2f+bEBX7R2yz0=" parent-hash "0JRYS5mysCKe92s8So5WC7cbttP3haCBtScjU64BJs0=" with-interface 09:00:00
4: allow id 1d6b:0001 serial "0000:00:04.2" name "UHCI Host Controller" hash "BSaNQWADaBI31jUqbck0N56uRuh3uVT1Vk4rdoD0ghs=" parent-hash "prVi21GR+cpMC0ykIE8H9TC9QoaAkFrbmw2PLcWNGkw=" with-interface 09:00:00
10: allow id 1b1c:1ab1 serial "000024937962" name "Voyager" hash "CrXgiaWIf2bZAU+5WkzOE7y0rdSO82XMzubn7HDb95Q=" parent-hash "JDOb0BiktYs2ct3mSQKopnOOV2h9MGYADwhT+oUtF2s=" via-port "1-3" with-interface 08:06:50

Preventing a Device from Interacting with the System

To prevent devices from interacting with the system, you can either block them, which means the system can see them but not use them, or you can reject them, which means the system cannot see them at all.

Use the usbguard block-device command with the device ID number to set its rule target to block.

[root@demo ~]# usbguard block-device ID

Use the usbguard reject-device command with the device ID number to set its rule target to reject.

[root@demo ~]# usbguard reject-device ID

Whitelisting and Blacklisting Devices

After it parses its command-line options, the usbguard daemon loads the usbguard-daemon.conf file, which it uses to configure runtime parameters of the daemon. Use the usbguard command with the -c option to modify the policy and authorization state of USB devices during runtime.

Edit the usbguard-daemon.conf file to create a USBGuard whitelist or blacklist.

USBGuard Configuration Options:

RuleFile=full path to file

The usbguard daemon loads the policy rule set from the file and will write new rules received through the IPC interface to the file.

IPCAllowedUsers=usernames

A space-delimited list of user names that the daemon will accept IPC connections from.

IPCAllowedGroups=groupnames

A space-delimited list of group names that the daemon will accept IPC connections from.

IPCAccessControlFiles=full path to directory

Path to a directory holding the IPC access control files.

ImplicitPolicyTarget=single value of allow, block, or reject

How to treat devices that do not match any rule in the policy. Target value is one of allow, block, or reject.

PresentDevicePolicy=policy

How to treat devices that are already connected when the daemon starts:

  • allow - authorize every connected device.

  • block - deauthorize every connected device.

  • reject - remove every connected device.

  • keep - synchronize the internal state and keep whatever state the device is currently in.

  • apply-policy - evaluate the rule set for every connected device.

PresentControllerPolicy=policy

How to treat USB controllers that are already connected when the daemon starts:

  • allow - authorize every connected device.

  • block - deauthorize every connected device.

  • reject - remove every connected device.

  • keep - synchronize the internal state and keep whatever state the device is currently in.

  • apply-policy - evaluate the rule set for every connected device.

Securing Access to the USBGuard IPC

The following configuration file instructs the usbguard daemon to load rules from the /etc/usbguard/rules.conf file and allow only users from the usbguard group to use the IPC interface:

RuleFile=/etc/usbguard/rules.conf
IPCAccessControlFiles=/etc/usbguard/IPCAccessControl.d/

To specify the IPC Access Control List (ACL), use the usbguard add-user or usbguard remove-user commands. In the following example, to allow users from the usbguard group to modify USB device authorization state, list USB devices, listen to exception events, and list USB authorization policy, enter the following command:

[root@demo ~]# usbguard add-user -g usbguard \
> --devices=modify,list,listen --policy=list --exceptions=listen

The usbguard daemon provides the USBGuard public inter-process communication (IPC) interface. In Red Hat Enterprise Linux, the access to this interface is by default limited to the root user only. In other environments, you should consider setting either the IPCAccessControlFiles option (recommended) or the IPCAllowedUsers and IPCAllowedGroups options to limit access to the IPC interface. Do not leave the ACL unconfigured. This exposes the IPC interface to all local users, which allows them to manipulate the authorization state of USB devices and modify the USBGuard policy.

Applying Rules to Specific Devices and Classes of Device

Policies built to allow or block specific devices are beneficial when devices can be examined and accurately identified. If accurate identification is not achievable, 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. In this case you can reject devices based on its USB class or set of characteristics. Rejecting a device or an entire class of devices will cause the kernel to remove them from the system.

Creating Policies that Match a Specific Device

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 above example you could use just the hash to match the device. However, using the name and serial attributes allows you to quickly assign rules to specific devices without computing the hash. On the other hand, the hash is the most specific value available to identify a device in USBGuard so it is the best attribute to use if you want a rule to match only one device.

Creating Policies that Match Multiple Devices

The following example allows USB mass storage devices (USB flash disks) and blocks everything else.

This policy blocks any device that has capabilities in addition to mass storage such, as a hidden keyboard. Devices with a hidden keyboard interface in a USB flash disk will be blocked. Only devices with a single mass storage interface will be allowed to interact with the operating system.

In the following output the interface-type represents a USB interface and should be formatted as three 8-bit colon-delimited hexadecimal numbers. For example:

{ interface class:subclass:protocol }

The policy consists of a single rule:

allow with-interface equals { 08:*:* }

In the above policy the blocking is implicit because a block rule was not included. Implicit blocking is useful to desktop users because a desktop applet listening to USBGuard events can ask the user for a decision if an implicit target was selected for a device.

Reject Devices with Suspicious Combination of Interfaces

A USB flash disk which implements a keyboard or a network interface is very suspicious. The following set of rules forms a policy which allows USB flash disks and explicitly rejects devices with an additional and suspicious interface.

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:*:* }

Blacklisting is the wrong approach and you should not just blacklist a set of devices and allow the rest. The policy above assumes that blocking is the implicit default. Rejecting a set of devices considered as "bad" is a good approach how to limit the exposure of the system to such devices as much as possible.

References

usbguard(1), usbguard-daemon(8), usbguard-daemon.conf(5), and usbguard-rules.conf(5) man pages.

Lab 5: USBGuard

For more information, refer to the Using USBGuard chapter in the Red Hat Enterprise Linux 7 Security Guide at https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/7/html/security_guide/sec-using-usbguard

Revision: rh415-7.5-813735c