The kernel is the part of an operating system that enforces security. Code that runs inside it is not bound by the controls it enforces. MITRE tracks the abuse of that fact as T1547.006, Kernel Modules and Extensions, with Persistence and Privilege Escalation as the tactics and Linux and macOS as the platforms.
How attackers use it
Loadable Kernel Modules (LKMs) are pieces of code that can be loaded into and unloaded from the kernel on demand. They extend the kernel without a reboot. A device driver is the usual example: it lets the kernel talk to hardware.
Used maliciously, an LKM can be a kernel-mode rootkit running at the highest operating system privilege, Ring 0. MITRE lists the common features of LKM based rootkits.
- Hiding themselves.
- Selectively hiding files, processes and network activity.
- Tampering with logs.
- Providing authenticated backdoors.
- Enabling root access for non-privileged users.
On macOS, the equivalent is the kernel extension, or kext. Kexts are loaded and unloaded with the kextload and kextunload commands, and they run as part of the kernel, so MITRE notes they are not governed by macOS security policies. They need to be signed with a developer ID that Apple has granted the privilege of signing kernel extensions. Developers without that privilege can still sign kexts, but they will not load unless System Integrity Protection (SIP) is disabled. With SIP enabled, the signature is verified before the kext is added to the auxiliary kernel collection.
Since macOS Catalina 10.15, kernel extensions have been deprecated in favor of System Extensions. MITRE notes kexts are still allowed as "Legacy System Extensions", because there is no System Extension for Kernel Programming Interfaces.
MITRE states that examples have been found in the wild, and that open source projects exist too. It lists several procedure examples on its page, including rootkits implemented as loadable kernel modules.
How to detect it
MITRE's detection strategy has one analytic per platform.
On Linux, monitor module load and unload activity through modprobe, insmod and rmmod, or direct manipulation of /lib/modules. Correlate with the installation of kernel headers, compilation commands, or downloads of .ko files. Look for anomalies such as unsigned module loading, or repeated load attempts from non-root users.
On macOS, detect user-initiated kextload commands and modifications to /Library/Extensions. Correlate with changes to the kext policy database or unauthorized developer signing identities, and alert on attempts to disable SIP or to load legacy extensions from unsigned sources.
A compiler on a production server is itself a strong signal. If a host that never builds code suddenly has kernel headers installed and a build running, ask why before you ask anything else.
How to reduce the risk
MITRE lists four mitigations.
- Antivirus and antimalware: common tools for detecting Linux rootkits include
rkhunterandchkrootkit, though rootkits may be designed to evade certain detection tools. Treat them as one signal, not a verdict. - Execution Prevention: application control and software restriction tools such as SELinux, KSPP and grsecurity MODHARDEN, plus Linux kernel tuning, can help restrict kernel module loading.
- Privileged Account Management: limit access to the root account and prevent users from loading modules and extensions through proper privilege separation, and by limiting privilege escalation opportunities.
- User Account Management: use MDM to disable users' ability to install or approve kernel extensions, and ensure that approved extensions match the policy set in
com.apple.syspolicy.kernel-extension-policy.
For Linux servers with a fixed set of hardware and drivers, locking module loading after boot is worth testing in staging. The kernel setting kernel.modules_disabled exists for this, but it cannot be reversed without a reboot, so plan the rollout carefully.
Check your own environment
Read-only commands. Linux first.
lsmod
cat /proc/sys/kernel/tainted
sysctl kernel.modules_disabled
- Does every loaded module belong to hardware or a service you run?
- A non-zero tainted value means the kernel has loaded something that taints it, such as an out-of-tree or unsigned module. Find out which one.
- Is module loading restricted on hosts that do not need it?
On macOS:
csrutil status
kmutil showloaded
systemextensionsctl list
- SIP should be enabled.
- Look for third-party extensions you cannot tie to a product on the approved list.
Quick check
Why is a kernel module more dangerous than a normal malicious program?
It runs in the kernel at the highest privilege, so it can hide itself, hide files, processes and network activity, tamper with logs and give root access, all from a position that the usual security controls do not govern.
What stops an arbitrary developer signed kext from loading on macOS?
Without the right Apple signing privilege, a kext will not load unless SIP is disabled. With SIP enabled, the signature is verified first.
Sources
- MITRE ATT&CK, Boot or Logon Autostart Execution: Kernel Modules and Extensions: https://attack.mitre.org/techniques/T1547/006