Today I Learned - kernel.modules_disabled

https://dfir.ch/posts/today_i_learned_lkm_kernel.modules_disabled/

10 Jul 2024 Table of Contents

Introduction
Hello, DFIR Kernel Module
Hardening
Conclusion

Introduction

The kernel.modules_disabled parameter is a security feature in the Linux kernel that prevents the loading and unloading of kernel modules. This setting is particularly useful for hardening a system against certain types of attacks, such as attempts to load malicious kernel modules (think rootkits) or manipulate the system at a low level. Mandiant recently published a blog post where they found, among other toolings used by the attackers, REPTILE. REPTILE is an open-source Linux rootkit, implemented as a loadable kernel module (LKM), that provides backdoor access to a system. Source: Cloaked and Covert: Uncovering UNC3886 Espionage Operations

By default, this setting is turned off:

sysctl -a | grep modules

kernel.modules_disabled = 0

Hello, DFIR Kernel Module

We will create a simple kernel module to showcase the kernel feature modules_disabled in action. We saved the code below under the name dfir.c in our home directory. The module is as simple as it can get: When the module is loaded, the string “Hello, DFIR!” will be logged inside the kernel’s message buffer. Subsequently, when the module exists, the string “Goodbye, DFIR!” will be logged.

#include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h>

// Called when the module is loaded static int __init dfir_init(void) { printk(KERN_INFO “Hello, DFIR!\n”); return 0; }

static void __exit dfir_exit(void) { printk(KERN_INFO “Goodbye, DFIR!\n”); }

module_init(dfir_init); module_exit(dfir_exit);

MODULE_LICENSE(“GPL”); MODULE_AUTHOR(“Stephan Berger”); MODULE_DESCRIPTION(“Simple Kernel Module for teaching Linux hardening techniques”); MODULE_VERSION(“0.1”);

Next, We create a file called Makefile in the same directory as our dfir.c source file:

obj-m += dfir.o

all: make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules

clean: make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean

And we compile our kernel module:

make

We see a lot of output, but the main thing to focus on is the filename of our compiled Kernel module, dfir.ko:

make -C /lib/modules/6.8.0-31-generic/build M=/root modules make[1]: Entering directory ‘/usr/src/linux-headers-6.8.0-31-generic’ warning: the compiler differs from the one used to build the kernel The kernel was built by: x86_64-linux-gnu-gcc-13 (Ubuntu 13.2.0-23ubuntu4) 13.2.0 You are using: gcc-13 (Ubuntu 13.2.0-23ubuntu4) 13.2.0 CC [M] /root/dfir.o MODPOST /root/Module.symvers CC [M] /root/dfir.mod.o LD [M] /root/dfir.ko BTF [M] /root/dfir.ko Skipping BTF generation for /root/dfir.ko due to unavailability of vmlinux make[1]: Leaving directory ‘/usr/src/linux-headers-6.8.0-31-generic’

We load the module with the command insmod:

insmod dfir.ko

Checking the logs (the command dmesg displays the message buffer of the kernel) if we see a successful load from our module - and yes, looks about right:

dmesg | tail

[..] [19323.400599] Hello, DFIR!

Same for unloading with the command rmmod:

rmmod dfir

dmesg | tail

[..] [19388.285645] Goodbye, DFIR!

Hardening

As stated above, the kernel setting modules_disabled is not enabled by default:

cat /proc/sys/kernel/modules_disabled

0

Let’s enable the feature to see the impact of it:

echo 1 > /proc/sys/kernel/modules_disabled

Once set, all subsequent attempts to load or unload kernel modules will fail. This change is permanent for the running kernel session and cannot be reverted without a reboot. Ensure all necessary modules are loaded before enabling this setting, as any attempt to load additional modules post-enablement will fail. As we see here, it’s not possible anymore to load our kernel module:

insmod dfir.ko

insmod: ERROR: could not insert module dfir.ko: Operation not permitted

And switching the flag back is not possible too, only after a reboot of the machine:

sysctl -w kernel.modules_disabled=0

sysctl: setting key “kernel.modules_disabled”: Invalid argument

And the unloading of already loaded modules is also not possible:

sysctl -w kernel.modules_disabled=1

kernel.modules_disabled = 1

rmmod dfir

rmmod: ERROR: ../libkmod/libkmod-module.c:856 kmod_module_remove_module() could not remove ‘dfir’: Operation not permitted rmmod: ERROR: could not remove module dfir: Operation not permitted

Conclusion

The kernel.modules_disabled parameter in the Linux kernel provides a robust security feature by preventing the loading and unloading of kernel modules, thereby hardening the system against low-level attacks, such as those involving rootkits. However, by default, this setting is disabled.

Updated: