Anthony Lineberry on /dev/mem Rootkits

Rootkits using /dev/mem could attack your system and leave virtually no trace—it even could be happening now!

The Interview

Anthony Lineberry is a security software engineer and Linux security
researcher. The concept of using /dev/kmem to rootkit Linux systems
was first written about by Silvio Cesare in 1998 and by devik in
Phrack
magazine in 2001. Besides bringing this seldom-discussed attack vector back
to people's attention, Anthony Lineberry has uncovered some new ways of
tricking the kernel to allocate memory for injected code.
Anthony and I chatted via e-mail immediately before and after his Black Hat
Europe presentation.

MB: Hi, Anthony. Thanks for taking the
time to talk to Linux Journal! It
looks like this attack has ramifications very similar to those of the
Loadable Kernel Module rootkit. Obviously, this isn't the best forum
for a detailed dissertation, but could you describe your /dev/mem attack for
our readers?

AL: We are essentially using the mem device to inject code
directly into the kernel. /dev/mem is just a character device that provides
an interface to physically addressable memory. Seeking to an offset and
performing a read will read from that physical location in memory.
Translating virtual addresses in the kernel to the physical addresses they
map to, you can use simple reads and writes to this device to hot-patch code
directly into the kernel. Using various heuristics, you can locate various
important structures in the kernel and manipulate them. At that point, you
are able to control behavior and manipulate almost anything inside the
kernel,
including system call tables, process lists, network I/O and so on.

MB: Does the attacker have to be root to locate and manipulate these
structures in memory?

AL: Yes, you would definitely have to be root to be able to read/write to
this device and manipulate any structures inside the kernel.

MB: How does this differ from LKM rootkits?

AL: LKMs, in general, will create a lot of “noise” when loaded into the
kernel. Using these techniques, we avoid all of that because of the fact
that we are injecting directly into physical memory. Using an LKM does make
it much easier to develop a rootkit. All of the effort can go into the
actual code, rather than having to determine reliably where everything is
inside the kernel. Although we can read/parse the export table inside
kernel memory to locate almost all exported symbols.

The general suggested way to mitigate kernel rootkits for Linux is to
configure a non-modular kernel and have all devices being used compiled
in. In this scenario, we are still able to get code into kernel space.

MB: Have you tested the attack in virtualized environments? Does
virtualized memory behave any differently?

AL: Yes, these methods will work in a virtualized environment. The main
difference I ran into was that some special instructions handled by
hypervisors behaved differently. Specifically in this case, the lidt
instruction I used for locating the IDT/System Call Table in memory would
return a bogus virtual address, but these problems were mostly trivial to
overcome.

MB:
What are the best defenses against /dev/mem attacks?

AL: The best defense is to enable CONFIG_STRICT_DEVMEM (originally called
CONFIG_NONPROMISC_DEVMEM in 2.6.26) in the kernel, which limits all
operations on the mem device to the first 256 pages (1MB) of physical
memory. This limitation will allow things like X and DOSEMU, which use this
device legitimately to still function properly, but keep anyone else from
reading outside of those low areas of memory. Unfortunately, the default
configuration leaves this protection disabled.

MB: Have you contacted any of the major Linux distributors (Red Hat,
Novell and so forth)? Have any of them committed to enabling this setting in
their default kernels?

AL: No, [although] many major distros do enable this setting by default in
their releases. I would like to plan on compiling a list of who
does/doesn't enable this.

Some Notes on Mitigation

As Anthony said, short of ripping /dev/mem and /dev/kmem out of your kernel
(which almost certainly would break things, especially in the X Window
System), the best defense is to compile CONFIG_STRICT_DEVMEM=y in your
kernel. The default kernels for Fedora and Ubuntu systems already have this
option compiled in. RHEL goes a step further, by using an SELinux policy
that also restricts access to /dev/mem.

If you don't know whether your system's kernel was compiled with
CONFIG_STRICT_DEVMEM=y, there are several different ways to find
out.
Depending on your Linux distribution, your system's running kernel's
configuration file may be stored in /boot, with a name like
config-2.6.28-11-generic. If so, you can grep that file for DEVMEM. If
not, your kernel may have a copy of its configuration in the form of a file
called /proc/config.gz, in which case you can use the command:

zcat /proc/config.gz | grep DEVMEM

Otherwise, you need to obtain source code for your running kernel, do a
make oldconfig (which actually extracts your running kernel's
configuration), and check the resulting .config file. In any of these
cases, if CONFIG_STRICT_DEVMEM is set to n rather than
y, you need to
compile a custom kernel.

To do so, after having done make oldconfig, which even if you already
knew your kernel lacked CONFIG_STRICT_DEVMEM enablement is a good idea,
because you're probably interested in only changing CONFIG_STRICT_DEVMEM
and leaving the rest of the kernel the same, you can do either make
menuconfig or make xconfig. In the resulting menu, select kernel
hacking, look for the option Filter access to /dev/mem, set it to
y, exit, save your configuration, and re-compile.

If this entire kernel-compiling process is new to you, refer
to your Linux distribution's official documentation for more detailed
instructions. The process of compiling a custom kernel is, nowadays, rather
distribution-specific, especially if you want to generate a custom RPM or
deb package (which is the least disruptive way to actually
install a
custom kernel on RPM- and deb-package-based systems).