Debian GNU/Linux · Filesystem & permissions

Block USB mass storage and FireWire kernel modules

When it fails: USB storage devices and FireWire can be used on the system. Anyone with physical access can copy data to a USB disk, bring in tools, or use FireWire direct memory access.

CB-DEB-FS-002mediumactiveautomatedautomated fixprofile serverprofile desktop-hardened

As released in v0.1.1 beta · pre-release. Current state.

Description

usb-storage is the driver for USB disks and keys, firewire-core the base of the FireWire (IEEE 1394) stack. This control blocks the modules listed in {{ modules }}: each one gets an install <module> /bin/false rule, so any load attempt fails, and a blacklist rule. A module that no installed kernel ships is compliant.

Debian cloud kernels do not ship these modules, so the check passes there without any configuration. uas (USB Attached SCSI) depends on usb-storage and is blocked with it.

Rationale

Removable storage is a common way to take data out of a system and to bring malware in. FireWire controllers can read and write host memory directly, which lets a device extract keys or bypass the login. A server rarely needs either.

Impact

USB disks and keys are no longer usable. Keyboards, mice and other USB devices keep working. On a hardened workstation, use the network or an approved channel to exchange files, or remove usb-storage from {{ modules }} and control devices with USBGuard instead.

Setting

Location/etc/modprobe.d/60-cirsec-usb-firewire.conf
DefaultUSB storage and FireWire modules load when a device is plugged in
Recommendedinstall /bin/false and blacklist for: {{ modules }}

Parameters

ParameterCoreServerServer hardenedDesktopDesktop hardenedBounds
moduleslist. Kernel modules to block, as named by modprobe.usb-storage, firewire-coreusb-storage, firewire-coreusb-storage, firewire-coreusb-storage, firewire-coreusb-storage, firewire-core

The value used is your override (tailoring file), else the profile's, else the one of the profile it extends, else the default. Bounds limit what an override may set.

Audit

For each module of {{ modules }}:

  1. modprobe --showconfig | grep -E '^(install|blacklist) <module>' must show install <module> /bin/false and blacklist <module> (dashes appear as underscores), or find /lib/modules -name '<module>.ko*' must find nothing.
  2. grep '^<module> ' /proc/modules (with underscores) must find nothing.

Automated: every check must pass. Scanners report each check by its id.

modules

Each listed module is blocked in the modprobe configuration, or not shipped, and not loaded.

script: |
  cfg=$(modprobe --showconfig 2>/dev/null) || exit 3
  rc=0
  for m in $CB_MODULES; do
    n=$(printf '%s' "$m" | tr - _)
    if grep -q "^$n " /proc/modules; then
      echo "$m: loaded"; rc=1; continue
    fi
    if printf '%s\n' "$cfg" | grep -Eq "^install $n (/usr)?/bin/(false|true)( |\$)" &&
      printf '%s\n' "$cfg" | grep -qx "blacklist $n"; then
      echo "$m: blocked"
    elif [ -z "$(find /lib/modules/ \( -name "$m.ko*" -o -name "$n.ko*" \) 2>/dev/null | head -n 1)" ] &&
      ! grep -qs "/$n.ko\$\|/$m.ko\$" /lib/modules/*/modules.builtin; then
      echo "$m: not shipped by any installed kernel"
    else
      echo "$m: can be loaded"; rc=1
    fi
  done
  exit $rc

Remediation

  1. Create /etc/modprobe.d/60-cirsec-usb-firewire.conf with, for each module of {{ modules }}:
    install <module> /bin/false
    blacklist <module>
    
  2. Unplug the devices and unload the modules with modprobe -r <module>, or reboot.
Restartnone
Disruptionlow

Rollback

Delete /etc/modprobe.d/60-cirsec-usb-firewire.conf. The modules load again when a device is plugged in.

modprobe-conf

f=/etc/modprobe.d/60-cirsec-usb-firewire.conf
cb_backup "$f"
{
  echo '# Written by CIRSEC Baselines CB-DEB-FS-002'
  for m in $CB_MODULES; do printf 'install %s /bin/false\nblacklist %s\n' "$m" "$m"; done
} >"$f"
chmod 644 "$f"
rc=0
for m in $CB_MODULES; do
  n=$(printf '%s' "$m" | tr - _)
  grep -q "^$n " /proc/modules || continue
  modprobe -r "$n" || { echo "$m is in use, it stays loaded until reboot" >&2; rc=1; }
done
exit $rc

Handwritten code reads parameters from CB_<NAME> environment variables. Each release turns these fixes into remediate.sh and an Ansible role per profile: dry run by default, a fix runs only when its check fails.

References

Mappings

FrameworkIDRelation
NIST SP 800-53 Rev. 55.1.1MP-7partial
NIST SP 800-53 Rev. 55.1.1CM-7related

How this control relates to the other framework's: equivalent, stricter, looser, partial or related.

Threats mitigated

  • related CB-DEB-FS-001 Block kernel modules for filesystems the system does not use

People and lifecycle

Authors
Verified2026-10-18 by Sn0wAlice on 12, Proxmox VM 922, Debian 12 genericcloud image, kernel 6.1.0-54-cloud-amd64. Passes unconfigured (modules not shipped by the cloud kernel); fix writes the modprobe rules, check reports them blocked; server-hardened profile.
Verified2026-10-18 by Sn0wAlice on 13, Proxmox VM 932, Debian 13 genericcloud image, kernel 6.12.113+deb13-cloud-amd64. Passes unconfigured (modules not shipped by the cloud kernel); fix writes the modprobe rules, check reports them blocked; server-hardened profile.
Introduced inv0.1.0
Created, updated2026-10-18, 2026-10-18
Translationsfr