Detecting and Capturing Kernel Modules with Tracee and eBPF
Security practitioners often need to investigate malicious artifacts in their environments, which can be challenging if those are deleted or loaded from memory. This is increasingly the case as threat actors are weaponizing Linux kernel modules to perform and hide their attacks. In this blog, we look into kernel modules and explain why they can be dangerous, how threat actors are using them, and how you can detect and capture them for investigation with the open source runtime security tool Tracee.
What are kernel modules?
A kernel module, also known as a loadable kernel mode or LKM, is an object file containing code that can extend the functionality of the running Linux kernel. Kernel modules can be saved as a file on the filesystem or located in a buffer in the machine’s memory. They can be loaded into and unloaded from the kernel upon demand. Their power lies in that they enable the extension of the kernel functionality without the need to reboot the system. Developers use kernel modules for a wide range of purposes, such as supporting new hardware and adding functionality, which requires high privileges or device access.
Why can kernel modules pose a threat?
Kernel modules, as the name implies, run in the machine’s kernel. This gives them almost unlimited access to the system's resources and the ability to easily bypass security mechanisms. That’s why threat actors commonly use them to hide their activity on a compromised host. To make matters worse, since kernel modules provide access to the kernel itself, attackers can also cause more severe damage to the system, because there’s practically nothing that could limit them in the environment.
On top of that, kernel modules can pose another threat. Even when a kernel module is used for legitimate goals, a bug or unhandled error in its code will likely cause a system fault and could crash the system.
How attackers use kernel modules
As part of their toolkit, attackers often use user-mode malware, which runs in the less-privileged user space. It can be any malicious code used for various purposes, such as opening a backdoor, stealing data, or hijacking resources. Such activity is often evident in the system and can easily be detected.
To avoid detection, attackers increasingly are using malicious kernel modules, also widely known as kernel rootkits, to conceal their actions. The role of kernel rootkits is to hide malware and its actions, as well as to disable or disrupt any security mechanisms that might interfere with malicious activity.
There are several ways for a kernel module to hide itself. Since most security solutions scan filesystems for malware, a sophisticated attacker will try to avoid writing malicious files to disk. In this case, one of the methods to conceal a kernel module from detection is to use the syscall init_module, which enables kernel module loading from a memory buffer rather than a file. This allows a threat actor to load a malicious kernel module without it being dropped to the filesystem, avoiding modern detection methods such as scanning solutions.
Why do kernel modules pose a greater threat in the cloud?
Kernel modules pose a greater threat in the cloud than to endpoints because they can allow privileged access to the host itself. Loading a kernel module in a container enables an attacker to access the kernel, which gives them immediate access to the host, allowing them to take control over (escape to) that host.
Once an attacker has successfully escaped to the host, they could gain access to other containers that are running on the same host, the host instance itself, and other host instances in the cluster and network. They could even collect secrets and tokens of the cloud accounts.
The capability to load a kernel module requires high privileges and, in fact, is often considered a misconfiguration. That’s why a securely configured container shouldn’t be able to load a kernel module. However, in our research activities at Team Nautilus, we frequently see them in the wild.
Detection of kernel module loading
A strong cloud security tool should detect these kinds of events. Tracee, an open source runtime security and forensics tool for Linux, can detect the loading of a kernel module both from the filesystem and from a memory buffer. Security researchers and practitioners can benefit from Tracee because they can receive alerts whenever a new kernel module is loaded, which is a rare event.
Why is it so critical to detect kernel module loading? Once a kernel module is loaded, it gains all the capabilities to hide from any detection solutions. So from that point on, it would become almost impossible to detect a rootkit in your environment.
Tracee’s kernel module capturing
One of the cool features of Tracee is the kernel module capturing. Tracee can dump a loaded kernel module to disk for researchers and practitioners to investigate. This works both for the finit_module, which loads the kernel module from the filesystem, as well as the init_module, which relies on the kernel module being loaded from memory. This feature is pretty exciting because it allows researchers for the first time to dump loaded kernel modules to a file and investigate them later for forensics.
Kernel rootkits — malicious kernel modules
In a recent blog post, we discussed how TeamTNT used kernel rootkits to hide their attacks. In the attack we examined, the threat actors used Diamorphine, an open source kernel rootkit that allows attackers to hide malicious files and processes.
If you’re curious to learn more about rootkits and see a live demo of Tracee, check out our talk at BsidesTLV 2022:
Example of kernel rootkit capturing
Let’s see how Tracee will detect the loading of Diamorphine.
By running Tracee with the -c module command line argument, we enable the kernel module capturing feature. When Diamorphine is loaded from a memory buffer by the malware component, Tracee logs the malicious loading and drops the original ELF file of the kernel module to the Tracee default directory -
/tmp/tracee/out. Security researchers can then scan and analyze this file to determine if it’s malicious, this way focusing their attention on an attack in progress.
Detection and capture of volatile kernel module rootkit
Stay safe with CNDR
Aqua Cloud Native Detection and Response (CNDR) can detect such malicious behavior by using signatures written by Team Nautilus, Aqua’s security research team. Read more about CNDR’s detection capabilities, how CNDR stopped a DreamBus botnet attack, and how it also caught an attack by the 8220 gang.