Mitigating USB-based attacks within OpenShift Container Platform

Updated -

Purpose

This document walks through protections that can be put in place to block USB-based attacks against OCP. These defensive measures are most appropriate for systems where implementing physical access controls is difficult or infeasible, such as a network-edge deployment. Reducing the attack surface for USB devices can significantly reduce the severity of many other vulnerabilities or eliminate their risk entirely.

This document references a Linux kernel vulnerability (CVE-2024-53104) and the associated USB Video Class driver (uvcvideo) as an example. While this example impacts the Linux kernel's, this document is generic enough to be used for any kernel module which relates to USB.

Note that if you have the OpenShift Compliance operator installed and applied the rhcos4-moderate or rhcos4-high profiles, USB access to your nodes is already restricted.

Blocking unused kernel modules via MachineConfig

If your OpenShift cluster does not use specific kernel modules (for example the uvcvideo module for CVE-2024-53104) Red Hat recommends mitigating this potential attack surface by preventing that module from loading as shown below. Utilize this solution to inspect which modules are currently loaded on a system. Note that removing a module will disable its functionality. In the case of UVC devices, removing the uvcvideo module prevents webcams or video capture devices from functioning properly.

To block a module from loading you’ll create a drop-in config in /etc/modprobe.d/ directory such as /etc/modprobe.d/ocp-deny-uvcvideo.conf based on Preventing kernel modules from being automatically loaded at system boot time as follows

blacklist uvcvideo
install uvcvideo /bin/false

To create this file on OpenShift nodes you will create a new MachineConfig object which defines the file with content similar to above, the contents section is the urlencoded, you may use the Butane tool to generate machineConfig resources in a more friendly manner. The following example would deploy the file on workers and will trigger a rolling restart. If you also wish to protect your control plane nodes, create a similar MachineConfig with this command: machineconfiguration.openshift.io/role: “master”.

apiVersion: machineconfiguration.openshift.io/v1
kind: MachineConfig
metadata:
  labels:
    machineconfiguration.openshift.io/role: worker
  name: 99-worker-deny-uvcvideo
spec:
  config:
    ignition:
      version: 3.2.0
    storage:
      files:
        - contents:
            compression: ""
            source: data:,blacklist%20uvcvideo%0Ainstall%20uvcvideo%20%2Fbin%2Ffalse%0A
          mode: 420
          overwrite: true
          path: /etc/modprobe.d/ocp-deny-uvcvideo.conf

Assuming the contents above are saved as 99-worker-deny-uvcvideo.yaml, this policy could be applied by running the following command as an admin: oc apply -f 99-worker-deny-uvcvideo.yaml

oc apply -f 99-worker-deny-uvcvideo.yaml
machineconfig.machineconfiguration.openshift.io/99-worker-deny-uvcvideo created

Blocking the uvcvideo kernel module via Compliance Operator Profiles

You can choose to modify your node configurations using existing Compliance Operator profiles or by creating a tailored profile. To use this method, you must first install the Compliance Operator on your Cluster. To disable the use of USB devices, you can run the rhcos4-moderate or rhcos4-high profile. If you only want to disable a specific module such as uvcvideo you can create a tailored profile instead as shown below.

Steps to Create a TailoredProfile to check and disable a module:

1. Create a TailoredProfile

Save this file as deny-uvc-profile.yaml:

apiVersion: compliance.openshift.io/v1alpha1
kind: TailoredProfile
metadata:
  name: deny-uvc-profile
  namespace: openshift-compliance
  annotations:
    ## We need to set product type to Node for rhcos4 profile rules
    compliance.openshift.io/product-type: Node
spec:
  description: a profile will check if uvcvideo module is disabled
  enableRules:
    - name: rhcos4-kernel-module-uvcvideo-disabled
      rationale: CVE-2024-53104 documents a vulnerability found in the Linux kernel's USB Video Class driver. The vulnerability exists in functionality used by the USB Video Class driver to decode the format of video frames.
  title: Ensure uvcvideo module is being disabled

Activate the TailoredProfile:

$ oc apply -f deny-uvc-profile.yaml

How to enable usbguard
The following rules (which enable and configure usbguard) are shipped by default in rhcos4-moderate and rhcos4-high profiles provided in Compliance Operator
- rhcos4-package-usbguard-installed
- rhcos4-service-usbguard-enabled
- rhcos4-configure-usbguard-auditbackend
- rhcos4-usbguard-allow-hid-and-hub
You can either run a scan for rhcos4-moderate and rhcos4-high profile and apply remediation or use the below tailoredProfile. Save this file as enable-usbguard-tp.yml:

apiVersion: compliance.openshift.io/v1alpha1
kind: TailoredProfile
metadata:
  name: enable-usbguard-tp
  namespace: openshift-compliance
  annotations:
    ## We need to set product type to Node for rhcos4 profile rules
    compliance.openshift.io/product-type: Node
spec:
  description: a profile will check if uvcvideo module is disabled
  enableRules:
    - name: rhcos4-package-usbguard-installed
      rationale: we need to check and install usbguard
    - name: rhcos4-service-usbguard-enabled
      rationale: usbguard will be installed after install
    - name: rhcos4-configure-usbguard-auditbackend
      rationale: verify that Linux Audit logging is enabled for the USBGuard daemon
    - name: rhcos4-usbguard-allow-hid-and-hub
      rationale: We will allow Human Interface Devices and hubs
  title: Ensure USBGuard is enabled

Activating the usbguard rule will trigger multiple reboots:

$ oc get cr
NAME                                                      STATE
enable-usbguard-tp-master-package-usbguard-installed      Applied
enable-usbguard-tp-master-service-usbguard-enabled        MissingDependencies
enable-usbguard-tp-master-usbguard-allow-hid-and-hub      MissingDependencies
enable-usbguard-tp-worker-package-usbguard-installed      Applied
enable-usbguard-tp-worker-service-usbguard-enabled        MissingDependencies
enable-usbguard-tp-worker-usbguard-allow-hid-and-hub      MissingDependencies

USBGuard Service has to be installed before it can be enabled, so you would have to wait for the remediation to be applied and MachineConfigPool to become ready and then rerun the scan.

2. Create ScanSettingBinding that references the created TailoredProfile

Save this file as deny-uvc-ssb.yaml:

apiVersion: compliance.openshift.io/v1alpha1
kind: ScanSettingBinding
metadata:
  name: deny-uvc-ssb
  namespace: openshift-compliance
profiles:
  - apiGroup: compliance.openshift.io/v1alpha1
    kind: TailoredProfile
    name: deny-uvc-profile
settingsRef:
  apiGroup: compliance.openshift.io/v1alpha1
  kind: ScanSetting

  name: default-auto-apply

You can include this TailoredProfile with other existing profiles in a ScanSettingBinding you are already using or create a new one.

Use the default-auto-apply will automatically apply the generated remediation otherwise if you want to apply remediation manually you use default ScanSetting here adjust and create ScanSetting to let operator know what pool you want to apply the Scan and remediation to, we have master, worker role as default.

Activate the ScanSettingBinding

$ oc apply -f deny-uvc-ssb.yaml

3. Check TailoredProfile and ScanSettingBinding are in Ready States

$ oc get tp
NAME               STATE
deny-uvc-profile   READY

$ oc get ssb
NAME           STATUS
deny-uvc-ssb   READY

4. Wait for scan to finish and remediation to be applied

$ oc get scan
NAME                      PHASE   RESULT
deny-uvc-profile-master   DONE    NON-COMPLIANT
deny-uvc-profile-worker   DONE    NON-COMPLIANT

$ oc get ccr
NAME                                                      STATUS   SEVERITY
deny-uvc-profile-master-kernel-module-uvcvideo-disabled   FAIL     medium
deny-uvc-profile-worker-kernel-module-uvcvideo-disabled   FAIL     medium

We can see that the compliance remediation has been generated and applied to the cluster

$ oc get cr
NAME                                                      STATE
deny-uvc-profile-master-kernel-module-uvcvideo-disabled   Applied
deny-uvc-profile-worker-kernel-module-uvcvideo-disabled   Applied

We can inspect the generated compliance remediation:

$ oc get cr -o yaml
apiVersion: v1
items:
- apiVersion: compliance.openshift.io/v1alpha1
  kind: ComplianceRemediation
  metadata:
    creationTimestamp: "2025-02-10T23:33:44Z"
    generation: 2
    labels:
      compliance.openshift.io/scan-name: deny-uvc-profile-master
      compliance.openshift.io/suite: deny-uvc-ssb
    name: deny-uvc-profile-master-kernel-module-uvcvideo-disabled
    namespace: openshift-compliance
  spec:
    apply: true
    current:
      object:
        apiVersion: machineconfiguration.openshift.io/v1
        kind: MachineConfig
        spec:
          config:
            ignition:
              version: 3.1.0
            storage:
              files:
              - contents:
                  source: data:,install%20uvcvideo%20/bin/false%0Ablacklist%20uvcvideo%0A
                mode: 420
                overwrite: true
                path: /etc/modprobe.d/uvcvideo.conf
    outdated: {}
    type: Configuration
  status:
    applicationState: Applied

Wait for all nodes to finish updating:

$ oc get mcp
NAME     CONFIG                                             UPDATED   UPDATING   DEGRADED   MACHINECOUNT   READYMACHINECOUNT   UPDATEDMACHINECOUNT   DEGRADEDMACHINECOUNT   AGE
master   rendered-master-2d509f401a173fe88c986bbfb94443e3   True      False      False      3              3                   3                     0                      63m
worker   rendered-worker-c0e83d6064f20d73d77adea67e4ce254   False     True       False      3              1                   3                     0                      63m

5. Rerun the ComplianceScan

To check if the remediation has taken effect:

$ oc compliance rerun-now scansettingbindings deny-uvc-ssb
Rerunning scans from 'deny-uvc-ssb': deny-uvc-profile-master, deny-uvc-profile-worker
Re-running scan 'openshift-compliance/deny-uvc-profile-master'
Re-running scan 'openshift-compliance/deny-uvc-profile-worker'

6. Verification

We can now see that all scans are in passing state:

$ oc get scan
NAME                      PHASE   RESULT
deny-uvc-profile-master   DONE    COMPLIANT
deny-uvc-profile-worker   DONE    COMPLIANT

$ oc get ccr
NAME                                                      STATUS   SEVERITY
deny-uvc-profile-master-kernel-module-uvcvideo-disabled   PASS     medium
deny-uvc-profile-worker-kernel-module-uvcvideo-disabled   PASS     medium

Optionally we can check on each node as well:

$oc debug node/<HOSTNAME-HERE> 
Temporary namespace openshift-debug-24ngm is created for debugging node...
Starting pod/<HOSTNAME-HERE> ...
To use host binaries, run `chroot /host`
Pod IP: <IP-SHOWN-HERE>
If you don't see a command prompt, try pressing enter.

sh-5.1# chroot /host

sh-5.1# cat /etc/modprobe.d/uvcvideo.conf 
install uvcvideo /bin/false
blacklist uvcvideo

sh-5.1# modprobe uvcvideo
modprobe: ERROR: Error running install command '/bin/false' for module uvcvideo: retcode 1
modprobe: ERROR: could not insert 'uvcvideo': Invalid argument

sh-5.1# lsmod | grep uvcvideo

Note about USBGuard

When you use the rhcos4-moderate or rhcos4-high profiles, the following rules are used to enable and configure USBGguard:
- rhcos4-package-usbguard-installed
- rhcos4-service-usbguard-enabled
- rhcos4-configure-usbguard-auditbackend
- rhcos4-usbguard-allow-hid-and-hub

You can either run a scan for one of those profiles and apply the remediations or use them in a tailoredProfile, following the example above. USBGuard could be an additional protection layer.

This would be the YAML file:

apiVersion: compliance.openshift.io/v1alpha1
kind: TailoredProfile
metadata:
  name: enable-usbguard-tp
  namespace: openshift-compliance
  annotations:
    ## We need to set product type to Node for rhcos4 profile rules
    compliance.openshift.io/product-type: Node
spec:
  description: a profile will check if uvcvideo module is disabled
  enableRules:
    - name: rhcos4-package-usbguard-installed
      rationale: we need to check and install usbguard
    - name: rhcos4-service-usbguard-enabled
      rationale: usbguard will be installed after install
    - name: rhcos4-configure-usbguard-auditbackend
      rationale: verify that Linux Audit logging is enabled for the USBGuard daemon
    - name: rhcos4-usbguard-allow-hid-and-hub
      rationale: We will allow Human Interface Devices and hubs
  title: Ensure USBGuard is enabled

Applying the usbguard rule will trigger multiple reboots:

$oc get cr
NAME                                                      STATE
enable-usbguard-tp-master-package-usbguard-installed      Applied
enable-usbguard-tp-master-service-usbguard-enabled        MissingDependencies
enable-usbguard-tp-master-usbguard-allow-hid-and-hub      MissingDependencies
enable-usbguard-tp-worker-package-usbguard-installed      Applied
enable-usbguard-tp-worker-service-usbguard-enabled        MissingDependencies
enable-usbguard-tp-worker-usbguard-allow-hid-and-hub      MissingDependencies

The USBGuard service needs to be installed before it can be enabled, so you would have to wait for the remediation to be applied and MachineConfigPool to become ready and then rerun the scan.

How to remove mitigations

Once a fixed version of the module has been installed, consider removing the mitigation. To do so, either unapply the remediation or delete the MachineConfig resource.

Comments