Exploiting the Linux Kernel for
Privilege Escalation
Pietro Borrello
Who am I
Ph.D. Student at Sapienza University of Rome
Working on:
• Microarchitectural Attacks
• Side Channels
• Program Analysis
• Fuzzing
TRX
Our Journey
1. Setting up the environment
2. First Steps in Kernel Memory
Corruption
3. Gaining Root Privileges
4. Linux Kernel Mitigations
5. Bypassing Linux Kernel
Mitigations
Setting Up the
Environment
1 2 3
Fetch & Build Run the Kernel Debug the
the Linux Kernel in qemu kernel
Fetch & Build the Linux Kernel
1. Get in touch with Kernel source code on bootlin
Fetch & Build the Linux Kernel
1. Get in touch with Kernel source code on bootlin
2. Use buildroot to configure and build the kernel
Fetch & Build the Linux Kernel
1. Get in touch with Kernel source code on bootlin
2. Use buildroot to configure and build the kernel
3. Collect the output files
Debug the Kernel
see:
• https://github.com/hugsy/gef
• https://github.com/martinradev/gdb-pt-dump
First Steps in
Kernel Memory
Corruption
1 2 3
Kernel Attack Common Bugs Arbitrary Code
Surface Execution: is it
necessary?
Linux Kernel Attack Surface
OEM
Customizations Device
Loadable Drivers
Kernel
Modules
syscall
interface
Coprocessors
Common bugs
• Read out of bounds
• Writes out of bounds
• Type confusions
• Use After Free
• Uninitialized memory
• Integer Overflows
Common bugs
• Read out of bounds
• Writes out of bounds
• Type confusions
• Use After Free
• Uninitialized memory
• Integer Overflows
Common More Interesting bugs
• Direct userspace pointer usage
• TOCTOUs / Double Fetches
• Race Conditions
• Improper Permissions
Direct userspace pointer usage
The kernel has to deal with pointers from userspace that are untrusted
What if ptr or ptr->data points to kernel space?
Direct userspace pointer usage
The kernel has to deal with pointers from userspace that are untrusted
What if ptr or ptr->data points to kernel space?
-> Add check to verify
Double Fetches
Let’s assume you need to copy content from userspace
Double Fetches
Let’s assume you need to copy content from userspace
Ok maybe this is secure…
Double Fetches
Let’s assume you need to copy content from userspace
Arbitrary Code Execution: is it
necessary?
ring0
FREE
root
user
Gaining Root
Privileges
1 2 3
The ACE way The AAW way The 1337 way
ACE: Arbitrary Code Execution
AAW: Arbitrary Address Write
AAR: Arbitrary Address Read
1337: 1337
The ACE way - ret2usr
Let’s start easy:
• controlled function pointer
• no kernel mitigations in place
…but what should we do?
The ACE way - ret2usr
The goal is to achieve root privileges in the system.
• The kernel holds privilege information in the task_struct
The ACE way - ret2usr
The goal is to achieve root privileges in the system.
• The kernel holds credentials information in the task_struct
• uses functions to update them
The ACE way - ret2usr
The goal is to achieve root privileges in the system.
• The kernel holds credentials information in the task_struct
• uses functions to update them
• and to generate new ones
The ACE way - ret2usr
1. Leverage the same kernel functions to change credentials to root ones.
• how to find the location of these functions?
/proc/kallsyms: list of the addresses of all symbols loaded in the kernel
• without KASLR: get the address directly
• with KASLR: get the offset w.r.t. kernel .text base
The ACE way - ret2usr
1. Leverage the same kernel functions to change credentials to root ones
The ACE way - ret2usr
1. Leverage the same kernel functions to change credentials to root ones
Now we are root! But how to safely return to userspace to spawn a shell?
The ACE way - ret2usr
1. Leverage the same kernel functions to change credentials to root ones
2. Return to userspace by restoring the right context
The ACE way - ret2usr
1. Leverage the same kernel functions to change credentials to root ones
2. Return to userspace by restoring the right context
3. Enjoy root
The AAW way
What if we don’t have kernel arbitrary code execution?
Let’s assume an Arbitrary Address Write primitive
The AAW way
What if we don’t have kernel arbitrary code execution?
Let’s assume an Arbitrary Address Write primitive
… but what and where to write?
The AAW way
We already know some interesting pointers to overwrite…
commit_creds just overwrites them
The AAW way
We already know some interesting pointers to overwrite…
commit_creds just overwrites them
The AAW way
Overwrite real_cred and cred in current_task with root credentials
The AAW way
Overwrite real_cred and cred in current_task with root credentials
A few details:
• how to find current_task
• how to generate/find root credentials
The AAW way
• how to find current_task
The AAW way
• how to find current_task
• how to generate/find root credentials
there already exists init_cred as a global variable in the kernel data
The AAW way
1. Overwrite current_task ->real_cred and current_task ->cred with init_cred
2. Enjoy root
The 1337 way - modprobe_path
modprobe is used to add a loadable kernel module to the Linux kernel
• the kernel can automatically load
modules executing modprobe as root
when needed. e.g., using different
network protocols, unknown files
• the path to modprobe binary is stored
in the modprobe_path global var
• modprobe_path is in a RW kernel
page by default
The 1337 way - modprobe_path
1. overwrite modprobe_path using a kernel AAW primitive with the path
of a binary that we control
2. trigger modprobe_path execution, .e.g., executing unknown binary format
3. Enjoy root
Linux Kernel
Mitigations
1 2 3
Prevent KASLR & Friends Kernel Hardening
code/data
hijacking
Prevent hijacking - SMEP
We saw how controlling a code pointer may just allow us to jump back to
userspace, and execute arbitrary code at ring0
Supervisor Mode Execution Protection:
• prevent executing from userland pages when in kernel mode
• controlled by 20th bit of cr4
jmp
ring0 ring3
kernel userspace
Prevent hijacking - SMEP
• controlled by 20th bit of cr4
Can we bypass it?
1. jump to native_write_cr4 and reset the bit
2. jump to userspace
jmp
ring0 ring3
kernel userspace
Prevent hijacking - SMEP
• controlled by 20th bit of cr4
Can we bypass it?
1. jump to native_write_cr4 and reset the bit
the kernel explicitly prevents writes to sensitive cr4 bits
jmp
ring0 ring3
kernel userspace
Prevent hijacking - SMEP
Can we disable it? NO
What if we ROP on kernel code?
1. find pivoting gadget in kernel code mov rsp, 0x1337000; ret;
2. pivot to ropchain from user data
prepare_kernel_cred(0);
commit_creds();
swapgs; ret;
iret;
Prevent hijacking - SMAP
We saw how controlling a pointer may allow us to ROP from userspace, and
execute arbitrary code at ring0
Supervisor Mode Access Prevention:
• prevent accessing data from userland pages when in kernel mode
• controlled by 21st bit of cr4 (pinned bit)
access
ring0 ring3
kernel userspace
Prevent hijacking - SMAP
Supervisor Mode Access Prevention:
• prevent accessing data from userland pages when in kernel mode
Wait… how do you pass data to the kernel then?
syscall: write(1, buffer, 0x100);
access
ring0 ring3
kernel userspace
Prevent hijacking - SMAP
Supervisor Mode Access Prevention:
• prevent accessing data from userland pages when in kernel mode
• Fast way to disable SMAP through kernel EFLAGS.AC
Prevent hijacking - KPTI
Kernel Page Table Isolation
prevent attacks on the shared user/kernel address space, with two sets of
pages:
1. userspace page tables with minimal amount of kernel pages
2. kernel page tables with user pages mapped as NX
Mitigation with an prepare_kernel_cred(0); prepare_kernel_cred(0);
effect similar to
SMEP for exploitation commit_creds(); commit_creds();
swapgs; ret; KPTI trampoline
iret;
KASLR
Kernel Address Space Layout Randomization
Randomize different sections of the kernel independently:
• text segment
• modules
• direct physical map
• …
Lower entropy than userspace ASLR, but here a crash means system crash
-> need to leak KASLR addresses using an AAR primitive/side-channels
FG-KASLR
Function Granular Kernel Address Space Layout Randomization
Random shuffle of kernel code on a per-function granularity at every boot
-> a single leak is no more sufficient to derandomize the entire kernel
address space
prepare_kernel_cred commit_creds do_mmap
commit_creds do_mmap prepare_kernel_cred
copy_from_user prepare_kernel_cred copy_from_user
do_mmap copy_from_user commit_creds
FG-KASLR
However…
Certain regions of the kernel cannot be randomized.
• initial _text region
• KPTI trampoline
• kernel symbol table ksymtab
FG-KASLR
Wait what? ksymtab
It is needed to export symbols so that they could be used by kernel modules
FG-KASLR
Wait what? ksymtab
It is needed to export symbols so that they could be used by kernel modules
FG-KASLR
Wait what? ksymtab
It is needed to export symbols so that they could be used by kernel modules
Bypass:
1. Leak _text image base address using an AAR
2. Compute the address of _ ksymtab_<func> from _ text base
3. Leak the value_offset entry from _ ksymtab_<func>
Structure Layout Randomization
Usually fields in a C structure are laid out by the compiler in order of their
declaration.
field1
field2
field3
field4
Structure Layout Randomization
Usually fields in a C structure are laid out by the compiler in order of their
declaration.
Randomly rearrange fields at compilation time, using a random seed.
field4
field1
field3
field2
Structure Layout Randomization
task_struct may have their layout randomized. How can we overwrite creds?
Structure Layout Randomization
task_struct may have their layout randomized. How can we overwrite creds?
-> need to reverse engineer the vmlinux binary to recover the field offsets
Kernel Hardening
Build the kernel with different security options to harden its attack surface
• Attack surface reduction
• Enable security features
Kernel Hardening
Build the kernel with different security options to harden its attack surface
• Attack surface reduction
• INIT_STACK_ALL: initialize all stack variables
• SECURITY_DMESG_RESTRICT: avoid leaks of kernel pointers in dmesg
• PANIC_ON_OOPS: panic on kernel oops
• MODULE_SIG_FORCE: force modules to be signed
• BPF_JIT=n: disable BPF jitter
Kernel Hardening
Build the kernel with different security options to harden its attack surface
• Enable security features
• STACKPROTECTOR_STRONG: improve stack canary coverage
• DEBUG_CREDENTIALS: keep track of pointers to cred struct
• HARDENED_USERCOPY: validate memory regions of user pointers
• SLAB_FREELIST_RANDOM/HARDENED: randomize/fortify allocators
• RANDOMIZE_KSTACK_OFFSET: randomize stack offset at each syscall
Kernel Hardening - USERMODEHELPER
The modprobe_path technique is so powerful that it has his own mitigation
CONFIG_STATIC_USERMODEHELPER:
Force all usermode helper calls through a single binary
Kernel Hardening - SELINUX
SELinux defines access controls for every resource in a system.
• mandatory access control decisions made based on security policies
• every process and system resource has a SELinux context
• whitelist of the possible interactions between the SELinux contexts
Bypassing
Linux Kernel
Mitigations
1 2
kROP on Leveraging
physmap Useful Structures
kROP - SMAP
SMAP prevents accessing data from userland pages when in kernel mode
Is Kernel ropping dead then?
access
ring0 ring3
kernel userspace
kROP - SMAP
SMAP prevents accessing data from userland pages when in kernel mode
Is Kernel ropping dead then?
• directly place the chain in kernel land if you have control over some data
• indirectly place the chain in kernel land
access
ring0 ring3
kernel userspace
kROP - SMAP
SMAP prevents accessing data from userland pages when in kernel mode
Is Kernel ropping dead then?
• directly place the chain in kernel land if you have control over some data
• indirectly place the chain in kernel land
T LY?
IR EC
IND
access
ring0 ring3
kernel userspace
kROP - physmap
The kernel has a view of the whole physical memory mapped in physmap
-> This means userspace pages are aliased in kernel memory!
kROP - physmap
The kernel has a view of the whole physical memory mapped in physmap
-> This means userspace pages are aliased in kernel memory!
access
ring0 ring3
kernel userspace
userspace
alias
kROP - physmap
The kernel has a view of the whole physical memory mapped in physmap
-> This means userspace pages are aliased in kernel memory!
• originally the mapping was RWX! access
(now fixed)
ring0 ring3
• SMAP bypass: kernel userspace
1. spray ropchain pages in userspace
2. locate the page in physmap using AAR
3. ROP to physmap userspace
alias
Leveraging useful structures
During kernel exploitation you have a lot of control on the objects that are
allocated as consequence of actions performed in userspace.
Often you have bugs that give you limited capabilities during exploitation
and want to:
• promote an out-of-bound read/write to AAR/W
• promote AAR/W to RIP control
• RIP control to ACE
Let’s look at some useful structures the kernel uses and that we can leverage
Useful structures - tty_struct
Created in kernel heap for each open(“/dev/ptmx”) syscall
-> useful for leaks and RIP control
Leak kernel heap address
Leak kernel base + RIP control
Useful structures - msg_msg
Created in kernel heap for each msgsnd() syscall
-> Variable in size + up to 4048 bytes of arbitrary data
Leak kernel heap address
Copy of user data
Useful functions - userfaultfd
userfaultfd lets you handle page faults on userspace, by defining a handler
that will be called to manage virtual memory.
But why is it useful?
-> we can make the kernel hang on user data access, while waiting for the
handler execution
-> deterministically enlarge race condition windows
Useful functions - setxattr
For each setxattr syscall the kernel allocates a buffer in heap with data
completely controlled by userspace. Couple with userfaultfd to avoid dealloc
Copy of user data in
kernel heap
Takeaway
With strong enough exploitation primitives, any mitigation can be bypassed.
Are we doomed?
• coverage guided kernel fuzzing to find bugs:
https://github.com/google/syzkaller
• secure programming to avoid bugs:
https://github.com/Rust-for-Linux
Thanks
Do you have any questions?
[email protected] @borrello_pietro
CREDITS: This presentation template was created by
Slidesgo, including icons by Flaticon, infographics &
images by Freepik
Resources (1)
● GET IN THE MOOD: https://www.youtube.com/watch?v=G1IbRujko-A
● https://github.com/smallkirby/kernelpwn
● https://github.com/pr0cf5/kernel-exploit-practice
● https://lkmidas.github.io/posts/20210123-linux-kernel-pwn-part-1/
● https://lkmidas.github.io/posts/20210223-linux-kernel-pwn-modprobe/
● https://devilinside.me/blogs/small-steps-kernel-exploitation
● https://duasynt.com/blog/linux-kernel-heap-spray
Resources (2)
● https://ptr-yudai.hatenablog.com/entry/2020/03/16/165628
● https://googleprojectzero.blogspot.com/2020/02/mitigations-are-attack-surface-too.html
● https://blog.lexfo.fr/cve-2017-11176-linux-kernel-exploitation-part1.html
● https://meowmeowxw.gitlab.io/ctf/3k-2021-klibrary/
● https://google.github.io/security-research/pocs/linux/cve-2021-22555/writeup.html
● https://akulpillai.com/posts/learning_through_challenges1/
● https://github.com/R3x/How2Kernel
Resources (3)
● https://pr0cf5.github.io/ctf/2020/03/09/the-plight-of-tty-in-the-linux-kernel.html
● https://www.graplsecurity.com/post/kernel-pwning-with-ebpf-a-love-story