Ensure auditd Collects Information on Kernel Module Loading and Unloading

Description

To capture kernel module loading and unloading events, use following lines, setting ARCH to either b32 for 32-bit system, or having two lines for both b32 and b64 in case your system is 64-bit:


-w /usr/sbin/insmod -p x -k modules
-w /usr/sbin/rmmod -p x -k modules
-w /usr/sbin/modprobe -p x -k modules
-a always,exit -F arch=ARCH -S init_module,delete_module -F key=modules

The place to add the lines depends on a way auditd daemon is configured. If it is configured to use the augenrules program (the default), add the lines to a file with suffix .rules in the directory /etc/audit/rules.d.

If the auditd daemon is configured to use the auditctl utility, add the lines to file /etc/audit/audit.rules.

Rationale

The addition/removal of kernel modules can be used to alter the behavior of the kernel and potentially introduce malicious code into kernel space. It is important to have an audit trail of modules that have been introduced into the kernel.

Remediation

Shell script

The following script can be run on the host to remediate the issue.

#!/bin/bash

# First perform the remediation of the syscall rule
# Retrieve hardware architecture of the underlying system
# Note: 32-bit and 64-bit kernel syscall numbers not always line up =>
#       it's required on a 64-bit system to check also for the presence
#       of 32-bit's equivalent of the corresponding rule.
#       (See `man 7 audit.rules` for details )
[ "$(getconf LONG_BIT)" = "32" ] && RULE_ARCHS=("b32") || RULE_ARCHS=("b32" "b64")

for ARCH in "${RULE_ARCHS[@]}"
do
        PATTERN="-a always,exit -F arch=$ARCH -S init_module -S delete_module \(-F key=\|-k \).*"
        GROUP="modules"
        FULL_RULE="-a always,exit -F arch=$ARCH -S init_module -S delete_module -k modules"
        # Perform the remediation for both possible tools: 'auditctl' and 'augenrules'
<ns10:sub idref="xccdf_org.ssgproject.content_value_function_fix_audit_syscall_rule" use="legacy"/>
        fix_audit_syscall_rule "auditctl" "$PATTERN" "$GROUP" "$ARCH" "$FULL_RULE"
        fix_audit_syscall_rule "augenrules" "$PATTERN" "$GROUP" "$ARCH" "$FULL_RULE"
done

# Then perform the remediations for the watch rules
# Perform the remediation for both possible tools: 'auditctl' and 'augenrules'
<ns10:sub idref="xccdf_org.ssgproject.content_value_function_fix_audit_watch_rule" use="legacy"/>
fix_audit_watch_rule "auditctl" "/usr/sbin/insmod" "x" "modules"
fix_audit_watch_rule "augenrules" "/usr/sbin/insmod" "x" "modules"
<ns10:sub idref="xccdf_org.ssgproject.content_value_function_fix_audit_watch_rule" use="legacy"/>
fix_audit_watch_rule "auditctl" "/usr/sbin/rmmod" "x" "modules"
fix_audit_watch_rule "augenrules" "/usr/sbin/rmmod" "x" "modules"
<ns10:sub idref="xccdf_org.ssgproject.content_value_function_fix_audit_watch_rule" use="legacy"/>
fix_audit_watch_rule "auditctl" "/usr/sbin/modprobe" "x" "modules"
fix_audit_watch_rule "augenrules" "/usr/sbin/modprobe" "x" "modules"

Warning

This rule checks for multiple syscalls related to kernel module loading and unloading; it was written with DISA STIG in mind. Other policies should use a separate rule for each syscall that needs to be checked. For example:

  • audit_rules_kernel_module_loading_insmod
  • audit_rules_kernel_module_loading_rmmod
  • audit_rules_kernel_module_loading_modprobe