Shuffling the kernel Linux (aka FGKASLR)
This blog post is the first of a series which will present different elements of a class of attacks known as Control-Flow Hijack, and its defenses.
Here, we’ll introduce the concept of ASLR and explain a patch series that intends to fortify the existing implementation for the kernel Linux (FGKASLR).
Conclusion
FGKASLR is an important protection to mitigate against dangerous attacks that comes with virtually no cost.
Now let’s guide you to how we reached this conclusion.
ASLR
ASLR stands for Address Space Layout Randomization. It is a security feature that shuffles the program’s binary. Its main role is to protect against a class of attacks known as Control-Flow Hijack.
Control-Flow Hijack (why do we need ASLR?)
These are attacks that involve changing the control-flow from the program to a malicious one. An example is called stack-smashing, where the attacker injects a malicious program through a buffer overflow and corrupts a return address, diverging the control-flow of the program to the injected binary.
Figure 1: Stack-smashing
Nowadays we know that an attacker can take control of a target machine without the need of injecting any code, just by using the executable binary that is already available in clever ways.
Popular implementation
ASLR is already supported by most compilers and linkers. GCC for example
has the flag -fPIE
(reference)
which creates Position Independent
Executables. This implementation of ASLR will compile the program using
relative addresses for local assets, and a reference table for the global
ones. When the program is executed, the linker will place the binary in a
random offset in memory. The other libraries that are linked with the program
will also be placed in random offsets creating a unique distribution in memory
for every execution.
Figure 2: ASLR example
Most GNU/Linux distributions come with ASLR enabled by default. By using the
virtual file /proc/sys/kernel/randomize_va_space
we can tell the kernel if
the linker should randomize or not the addresses of the binaries.
How ASLR works against CFH?
ASLR is an important tool to mitigate CFH because the attacker will need to find out all the necessary addresses to perform the attack every time the program starts, and most of the time the attacker doesn’t even have the means to find these addresses.
From the example in Figure 1, ASLR would randomize the stack position inside the memory, so the attacker would need extra information to corrupt the return address to point to the injected code.
It’s important to note that ASLR doesn’t fully block CFH. It still possible that the attacker may find the address layout of a program through some vulnerability. However, ASLR adds a protection layer with virtually no cost that makes the attacker’s life a lot more complicated, now depending on another vulnerability to being able to set up the CFH.
Function Granular Kernel ASLR (FGKASLR)
Kernel ASLR (KASLR)
Currently, Linux already supports ASLR, but in a rather limited implementation. The kernel binary is composed of one blob, and the randomization applied at boot time only affects the offset of where the kernel is placed in memory. This implementation is called KASLR.
Figure 3: KASLR
If an attacker plans to perform a CFH, it needs to find that offset, but once it’s found, all the necessary addresses are also found since they will always be at a fixed distance from the offset.
The new implementation
FGKASLR proposes to shuffle every function inside the blob. Now if an attacker can find one address, this will give no information about the other required address, as they are randomly distributed inside the blob.
Figure 4: FGKASLR
This implementation is strongly based on .text
regions. This is how the
executable part of a binary is identified by the linker and loader.
It’s possible to have many .text
regions in the same binary.
There are 3 main changes introduced by the patch that implements FGKASLR:
- C code is now compiled with the flag
-ffunction-sections
. This flag is responsible for placing every function compiled in a separate.text
region. - A change in the entry and exit point of assembly functions so that when the FGKASLR is defined, these functions are pushed to separate text regions.
- A new code that is executed at boot is responsible for shuffling the text regions in memory.
Challenges in protecting the kernel
The kernel is very important to protect because the programs executed in its space have high execution privileges and access to most of the system resources. At the same time, protecting it is very challenging because it is a tool that almost every other software depends upon, so efficiency is a core requirement. This is why kernels are usually implemented in low-level languages and assembly. Unfortunately, one of the tradeoffs we must face when maximizing efficiency is security. We now face a situation where the kernel is written mostly in C, so there is no way to know if it has or not vulnerabilities that can be exploited by CFH, and many of the protections against these attacks come at the cost of efficiency, so they are often hard choices to make.
FGKASLR is beautiful because it’s an easy choice. The greatest cost it adds is only at boot time, when the text spaces are shuffled. Apart from that the shuffling can have some weird effects on cache alignment, which can make things worse in some cases, and better in others, but usually by such a small margin that it can easily be ignored. Besides that, it’s an even stronger implementation than the popular ones used in userspace, as they are usually done at library level, and this one is in function.
Extra curiosities
Windows implementation
Windows’ implementation of user-space ASLR is a bit different. The .dll
files
aren’t compiled to be position independent, so addresses references are solved
when the .dll
is loaded. When we combine this with the fact that the OS
tries to map the same .dll
in memory to different processes, two limitations
are shown:
- the
.dll
must be in the same memory position for every process. This means that if the address of the.dll
is leaked by one of the processes, that address can be used to exploit another. - In the case where process A and B are both using the same
.dll
, if we restart B while A is still running, the position of the.dll
will remain the same in B.
For kernel-space windows also use KASLR.
Attacks to KASLR
DrK
DrK is an attack that instead of exploiting a kernel memory vulnerability to leak the an address from the kernel, it uses hardware functionalities to do so.
Intel provides TSX instructions for implementing transactional memory operations. What is necessary to understand the attack is that these instructions create a code region in user space where any failure in execution returns the control to the user, even the ones like page fault which should block the execution and redirect the flow to the kernel to handle it.
The researchers found out that the system takes an amount of time to identify the failure, and that the time is different for each failure. By measuring the time the systems take to fail to access a random memory address, they can determine if that page is in kernel space and is executable.
Since there is no randomization inside the kernel besides the initial offset, once they find out where the kernel starts they will know its exact memory layout, enabling them to exploit any known memory corruption available.
With FGKASLR, finding where the kernel is would give no information of its layout.
CVE-2020-28588
The CVE is
related to a kernel bug where reading from /proc/pid/syscall
would leak
memory content, among them pointers to the kernel stack. This CVE was
present from kernel version 5.1 to 5.9. With the current KASLR, the
leaking of a single memory address could be enough to find the whole
kernel layout. With FGKASLR this leakage would give minimal information
to the attacker, mitigating greatly the hazard caused by the vulnerability.
Stay tuned
In other posts, we intend to better explain how CFH works to paint a better picture of why it can be such a dangerous attack, and we also intend to post about some other protections that exist against it. Stay tuned ;)