All operating systems are made up of at least two major components. The first and most important of these is the kernel. The kernel is at the center of the operating system and controls everything the operating system does, including managing memory, controlling the CPU, and even controlling what the user sees on the screen. The second element of the operating system is often referred to as user land and includes nearly everything else.
The kernel is designed to be a protected or privileged area that can only be accessed by root or other privileged accounts. This is for good reason, as access to the kernel can provide nearly unfettered access to the operating system. As a result, most operating systems provide users and services access only to user land, where the user can access nearly anything they need without taking control of the operating system.
Access to the kernel allows the user to change how the operating systems works, looks, and feels. It also allows them to crash the operating system, making it unworkable. Despite this risk, in some cases, the system admin must very carefully access the kernel for operational and security reasons.
In this chapter, we’ll examine how to alter the way the kernel works and add new modules to the kernel. It probably goes without saying that if a hacker can alter the target’s kernel, they can control the system. Furthermore, an attacker may need to alter how the kernel functions for some attacks, such as a man-in-the middle (MITM) attack, where the hacker places themselves between a client and server and can eavesdrop on or alter the communication. First, we’ll take a closer look at the kernel structure and its modules.
The kernel is the central nervous system of your operating system, controlling everything it does, including managing interactions between hardware components and starting the necessary services. The kernel operates between the user applications you see and the hardware that runs everything, like the CPU, memory, and hard drive.
Linux is a monolithic kernel that enables the addition of kernel modules. As such, modules can be added and removed from the kernel. The kernel will occasionally need updating, which might entail installing new device drivers (such as video cards, Bluetooth devices, or USB devices), filesystem drivers, and even system extensions. These drivers must be embedded in the kernel to be fully functional. In some systems, to add a driver, you have to rebuild, compile, and reboot the entire kernel, but Linux has the capability of adding some modules to the kernel without going through that entire process. These modules are referred to as loadable kernel modules, or LKMs.
LKMs have access to the lowest levels of the kernel by necessity, making them an incredibly vulnerable target for hackers. A particular type of malware known as a rootkit embeds itself into the kernel of the operating systems, often through these LKMs. If malware embeds itself in the kernel, the hacker can take complete control of the operating system.
If a hacker can get the Linux admin to load a new module to the kernel, the hacker not only can gain control over the target system but, because they’re operating at the kernel level of the operating system, can control what the target system is reporting in terms of processes, ports, services, hard drive space, and almost anything else you can think of.
So, if a hacker can successfully tempt a Linux admin into installing a video or other device driver that has a rootkit embedded in it, the hacker can take total control of the system and kernel. This is the way some of the most insidious rootkits take advantage of Linux and other operating systems.
Understanding LKMs is absolutely key to being an effective Linux admin and being a very effective and stealthy hacker.
Let’s take a look at how the kernel can be managed for good and ill.
The first step to understanding the kernel is to check what kernel your system is running. There are at least two ways to do this. First, we can enter the following:
kali >uname -a
Linux Kali 4.6.0-kalil-amd64 #1 SMP Debian 4.6.4-lkalil (2016-07-21) x86_64
The kernel responds by telling us the distribution our OS is running is Linux Kali, the kernel build is 4.6.4, and the architecture it’s built for is the x86_64 architecture. It also tells us it has symmetric multiprocessing (SMP) capabilities (meaning it can run on machines with multiple cores or processers) and was built on Debian 4.6.4 on July 21, 2016. Your output may be different, depending on which kernel was used in your build and the CPU in your system. This information can be required when you install or load a kernel driver, so it’s useful to understand how to get it.
One other way to get this information, as well as some other useful information, is to use the cat command on the /proc/version file, like so:
kali >cat /proc/version
Linux version 4.6.0-kalil-amd64 (devel@kali.org) (gcc version 5.4.0 20160909
(Debian 5.4.0-6) ) #1 SMP Debian 4.6.4-lkalil (2016-07-21)
Here you can see that the /proc/version file returned the same information.
With the right commands, you can tune your kernel, meaning you can change memory allocations, enable networking features, and even harden the kernel against outside attacks.
Modern Linux kernels use the sysctl command to tune kernel options. All changes you make with sysctl remain in effect only until you reboot the system. To make any changes permanent, you have to edit the configuration file for sysctl directly at /etc/sysctl.conf.
A word of warning: you need to be careful when using sysctl because without the proper knowledge and experience, you can easily make your system unbootable and unusable. Make sure you’ve considered what you’re doing carefully before making any permanent changes.
Let’s take a look at the contents of sysctl now. By now, you should recognize the options we give with the command shown here:
kali >sysctl -a | less
dev.cdrom.autoclose = 1
dev.cdrom.autoeject = 0
dev.cdrom.check_media = 0
dev.cdrom.debug = 0
--snip--
In the output, you should see hundreds of lines of parameters that a Linux administrator can edit to optimize the kernel. There are a few lines here that are useful to you as a hacker. As an example of how you might use sysctl, we’ll look at enabling packet forwarding.
In the man-in-the middle (MITM) attack, the hacker places themselves between communicating hosts to intercept information. The traffic passes through the hacker’s system, so they can view and possibly alter the communication. One way to achieve this routing is to enable packet forwarding.
If you scroll down a few pages in the output or filter for “ipv4” (sysctl -a | less | grep ipv4), you should see the following:
net.ipv4.ip_dynaddr = 0
net.ipv4.ip_early_demux = 0
net.ipv4.ip_forward = 0
net.ipv4.ip_forward_use_pmtu = 0
--snip--
The line net.ipv4.ip_forward = 0 is the kernel parameter that enables the kernel to forward on the packets it receives. In other words, the packets it receives, it sends back out. The default setting is 0, which means that packet forwarding is disabled.
To enable IP forwarding, change the 0 to a 1 by entering the following:
kali >sysctl -w net.ipv4.ip_forward=1
Remember that that sysctl changes take place at runtime but are lost when the system is rebooted. To make permanent changes to sysctl, you need to edit configuration file /etc/sysctl.conf. Let’s change the way the kernel handles IP forwarding for MITM attacks and make this change permanent.
To enable IP forwarding, open the /etc/sysctl.conf file in any text editor and uncomment the line for ip_forward. Open /etc/sycstl.conf with any text editor and take a look:
#/etc/sysctl.conf - Configuration file for setting system variables
# See /etc/sysctl.d/ for additional system variables.
# See sysctl.conf (5) for information.
#
#kernel.domainname = example.com
# Uncomment the following to stop low-level messages on console.
#kernel.printk = 3 4 1 3
##############################################################3
# Functions previously found in netbase
#
# Uncomment the next two lines to enable Spoof protection (reverse-path
# Turn on Source Address Verification in all interfaces to
# prevent some spoofing attacks.
#net.ipv4.conf.default.rp_filter=1
#net.ipv4.conf.all.rp_filter=1
# Uncomment the next line to enable TCP/IP SYN cookies
#
# Note: This may impact IPv6 TCP sessions too
#net.ipv4.tcp_syncookies=1
See http://lwn.net/Articles/277146/
# Uncomment the next line to enable packet forwarding for IPv4
➊ #net.ipv4.ip_forward=1
The relevant line is at ➊; just remove the comment (#) here to enable IP forwarding.
From an operating system–hardening perspective, you could use this file to disable ICMP echo requests by adding the line net.ipv4.icmp_echo_ignore_all=1 to make it more difficult—but not impossible—for hackers to find your system. After adding the line, you will need to run the command sysctl -p.
Linux has at least two ways to manage kernel modules. The older way is to use a group of commands built around the insmod suite—insmod stands for insert module and is intended to deal with modules. The second way, using the modprobe command, we will employ a little later in this chapter. Here, we use the lsmod command from the insmod suite to list the installed modules in the kernel:
kali >lsmod
Module Size Used by
nfnetlink_queue 20480 0
nfnetlink_log 201480 0
nfnetlink 16384 2 nfnetlink_log, nfnetlink_queue
bluetooth 516096 0
rfkill 0 2 bluetooth
--snip--
As you can see, the lsmod command lists all the kernel modules as well as information on their size and what other modules may use them. So, for instance, the nfnetlink module—a message-based protocol for communicating between the kernel and user space—is 16,384 bytes and used by both the nfnetlink_log module and the nf_netlink_queue module.
From the insmod suite, we can load or insert a module with insmod and remove a module with rmmod, which stands for remove module. These commands are not perfect and may not take into account module dependencies, so using them can leave your kernel unstable or unusable. As a result, modern distributions of Linux have now added the modprobe command, which automatically loads dependencies and makes loading and removing kernel modules less risky. We’ll cover modprobe in a moment. First, let’s see how to get more information about our modules.
To learn more about any of the kernel modules, we can use the modinfo command. The syntax for this command is straightforward: modinfo followed by the name of the module you want to learn about. For example, if you wanted to retrieve basic information on the bluetooth kernel module you saw when you ran the lsmod command earlier, you could enter the following:
kali >modinfo bluetooth
filename: /lib/modules/4.6.0-kali-amd64/kernel/net/bluetooth/bluetooth.ko
alias: net-pf-31
license: GPL
version: 2.21
description:Bluetooth Core ver 2.21
author: Marcel Holtman <marcel@holtmann.org>
srcversion: FCFDE98577FEA911A3DAFA9
depends: rfkill, crc16
intree: Y
vermagic: 4.6.0-kali1-amd64 SMP mod_unload modversions
parm: disable_esco: Disable eSCO connection creation (bool)
parm: disable_ertm: Disable enhanced retransmission mode (bool)
As you can see, the modinfo command reveals significant information about this kernel module which is necessary to use Bluetooth on your system. Note that among many other things, it lists the module dependencies: rfkill and crc16. Dependencies are modules that must be installed for the bluetooth module to function properly.
Typically, this is useful information when troubleshooting why a particular hardware device is not working. Besides noting things like the dependencies, you can get information about the version of the module and the version of the kernel the module was developed for and then make sure they match the version you are running.
Most newer distributions of Linux, including Kali Linux, include the modprobe command for LKM management. To add a module to your kernel, you would use the modprobe command with the -a (add) switch, like so:
kali >modprobe -a <module name>
To remove a module, use the -r (remove) switch with modprobe followed by the name of the module:
kali >modprobe -r <module to be removed>
A major advantage of using modprobe instead of insmod is that modprobe understands dependencies, options, and installation and removal procedures and it takes all of these into account before making changes. Thus, it is easier and safer to add and remove kernel modules with modprobe.
Let’s try inserting and removing a test module to help you familiarize yourself with this process. Let’s imagine that you just installed a new video card and you need to install the drivers for it. Remember, drivers for devices are usually installed directly into the kernel to give them the necessary access to function properly. This also makes drivers fertile ground for malicious hackers to install a rootkit or other listening device.
Let’s assume for demonstration purposes (don’t actually run these commands) that we want to add a new video driver named HackersAriseNewVideo. You can add it to your kernel by entering the following:
kali >modprobe -a HackersAriseNewVideo
To test whether the new module loaded properly, you can run the dmesg command, which prints out the message buffer from the kernel, and then filter for “video” and look for any alerts that would indicate a problem:
kali >dmesg | grep video
If there are any kernel messages with the word “video” in them, they will be displayed here. If nothing appears, there are no messages containing that keyword.
Then, to remove this same module, you can enter the same command but with the -r (remove) switch:
kali >modprobe -r HackersAriseNewVideo
Remember, the loadable kernel modules are a convenience to a Linux user/admin, but they are also a major security weakness and one that professional hackers should be familiar with. As I said before, the LKMs can be the perfect vehicle to get your rootkit into the kernel and wreak havoc!
The kernel is crucial to the overall operation of the operating system, and as such, it is a protected area. Anything that’s inadvertently added to the kernel can disrupt the operating system and even take control of it.
LKMs enable the system administrator to add modules directly into the kernel without having to rebuild the entire kernel each time they want to add a module.
If a hacker can convince the system admin to add a malicious LKM, the hacker can take complete control of the system, often without the system admin even being aware.