Dirty Pipe: CVE-2022-0847
Explanation of the Linux Dirty Pipe exploit
In this, we will go through the new linux kernel vulnerability that was discovered recently via a tryhackme room called DirtyPipe
High Level Overview
In March 2022, a researcher named Max Kellerman publicly disclosed a Linux Kernel vulnerability (nicknamed "Dirty Pipe" for its similarities to the notorious "Dirty Cow" exploit affecting older versions of the kernel) that allowed attackers to arbitrarily overwrite files on the operating system.Arbitrary file overwrites at the kernel level can be very easily leveraged to escalate privileges on the machine (i.e. to obtain administrator, or "root" privileges). This is a devastating vulnerability, made more so by its reach: any devices running a vulnerable version of the Linux kernel (including Android phones) are affected!
https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-0847
Little Deep Dive
Before we start exploiting the DirtyPipe vulnerability, we need to have a little deep dive into the low level of the linux kernel and methodology behind it.
What is a page ?
The smallest unit of memory managed by the CPU is a page(usually 4 kB). Everything in the lowest layer of Linux’s memory management is about pages.
If an application requests memory from the kernel, it will get a number of pages. All file I/O is also about pages, if you read data from a file, the kernel first copies a number of 4 kB chunks from the hard disk into kernel memory, managed by a subsystem called the page cache.
From there, the data will be copied to userspace. The copy in the page cache remains for some time, where it can be used again, avoiding unnecessary hard disk I/O, until the kernel decides it has a better use for that memory
When a process attempts to open a file, the kernel loads it into pages which are then made available to the userland process. This userland access can be granted either by being copied into user-space memory, or by keeping the pages in kernel-space but making them accessible via system calls(effectively special functions which are used to interact with the kernel).
What is a pipe ?
A pipe is a tool for unidirectional inter-process communication. One end is for pushing data into it, the other end can pull that data.
Pipes are characterised as having two ends — one for reading, and one for writing; you can see this for yourself in the way that anonymous pipes take the standard output of a process and write it into a pipe where it can be read by the standard input of the next program in the chain.
What is a splice() ?
The Linux kernel provides a system call called "splice()", which is effectively a shortcut designed to speed up the process of pushing the contents of a file into a pipe.
This optimisation is achieved by moving references to the pages storing the file contents, rather than moving the entirety of the data. In other words, splice() allows us to point a pipe at a page which is already loaded into memory, containing a section of a file originally opened by a process requesting read-only access.
By splicing a page into the pipe then writing our own arbitrary data to the pipe, we can overwrite the contents of the page
Usually when you write to a pip after splicing a file, no changes actually happens on the disk. Changes are made on the page buffer i.e in memory. Nothing is permanently altered and contents of the file remains unchanged. Then how does this exploit make changes to the file? Linux Kernel v5.8 (2020) added a new flag — PIPE_BUF_FLAG_CAN_MERGE . In simple terms, this flag tells the kernel that the changes written to the page pointed to by the pipe should be written directly back to the file that the page comes from. This means that the we have a flag that allow us to tell the the kernel to write the page back to the disk as data comes into it, we have a bug that allows us to specify arbitrary flags for a pipe, and we have a system call that inadvertently allows us to point pipes at page buffers which were opened as read-only.The exploit simply works like this -
The exploit first opens a target file with only-read permission.
The exploits creates a pipe that forces the addition of the PIPE_BUF_FLAG_CAN_MERGE.
Next the it uses the splice() to make the pipe point at the desired section of the target file. Then it writes the arbitrary data the user has specified into the pipe, thereby overwriting the page buffer.
With PIPE_BUF_FLAG_CAN_MERGE it overwrites the original file on the disk.
This means with the right code the attacker can overwrite any file on the system that have only-read level access. That means all the files that only root users have write access to. This could result in gaining direct access to root user or have same power as the root user.
Exploitation Example
Now after understanding the low-level methodology we can move towards actual exploitation on a linux system using the tryhackme room called DirtyPipe
Note - First connect to the tryhackme VPN then spin up the machine and login via SSH with the credentials provided in the task section
The copy of the original exploit that was developed by Max Kellerman's (original exploit) can be found in the /home/tryhackme/Exploit/PoC/poc.c . Basically the exploit does the same thing mentioned in the above section that helps us overwrite critical files controlled only by the root user.
The target file that comes in the mind that is controlled only the root user are /etc/passwd and /etc/shadow file. We can target any one of them. For this example we will target the /etc/passwd file because even though password hashes are usually stored in the restricted-access /etc/shadow in modern Linux systems, most Linux variants do still check to see if account password hashes are given in /etc/passwd.
The first step after logging into the target machine via SSH is to create a new entry for a new user in the /etc/passwd file format. We will use openssl to create a password hash for the new user. In the below command openssl is creating a password hash of "pass123" with a salt "THM".
After this we will re-arrange the generated hash in the format as /etc/passwd file for a new user named "chrollo"(You can choose username and password of your own choice"
Now after this we need to find the offset. The offset is where in the file the exploit should begin writing. In shorts which part of the file must get overwritten. Because the DirtyPipe vulnerability doesn't allow to append to any restricted file. We are going to have to pick an account and overwrite it. Realistically speaking, given the length of our passwd entry (hash inclusive), this will probably actually overwrite several accounts. Looking through the passwd file, the games account stands out as being a good candidate for a little-used account which we can afford to nuke for a few minutes. We can use grep with the -b switch to find the offset of games from the start of the file
The offset is revealed to be 189. Everything is set! Compile the exploit.
First we need to make sure that we safely backup the orignal /etc/passwd. The destructive nature of exploit might corrupt the system. So it is a good practice to have a backup of the critical files. Use cp /etc/passwd /tmp/passwd to copy the passwd file to /tmp. Now moving towards exploitation.
As we are overwriting existing entries in the password file, we also need to add a new line on at the end of our entry. This ensures that we avoid corrupting our entry with any remnants of the previous contents of the line.
The exploit worked successfully! Now SU into user chrollo - pass123
Got the access to root user. The exploit worked perfectly !
Alternate Exploitation
In the above section we exploited DirtyPipe with the Max Kellerman's original proof of concept exploit code. The original PoC allowed us to overwrite any file with arbitrary data at an offset of our choosing. After this many other PoC was developed by various experts.There is another exploit in /home/tryhackme/Exploit/Bl4sty/dirtypipez.c , As the directory structure suggests, this implementation was coded by @bl4sty, a security researcher who you may remember if you have already completed the "SudoVulns: Baron Samedit" room.
The original exploit code can be downloaded from bl4sty's website here; however, as mentioned previously, a copy has already been added to the lab machine.This exploit takes the arbitrary file write one stage further by abusing a rather special quality of the vulnerability. SUID Programs usually lose their SUID bit when you attempt to write to them; however, this does not happen with Dirty Pipe — in other words, we can write to any program that has permission to execute with higher privileges, without inadvertently destroying that extra permission.
Bl4sty's exploit capitalises on this. Instead of overwriting a file like /etc/passwd, it overwrites a user-specified SUID binary (such as /bin/su), injecting shellcode into it which then gets executed with the permissions of the privileged user (i.e. root). Specifically, the exploit hijacks the chosen SUID binary and forces it to create a backdoor binary in /tmp which has the SUID bit and calls /bin/sh. It then restores the targeted SUID binary to full working order by re-adding the overwritten section, and uses the newly created backdoor to grant the attacker a shell as the privileged user.
Now moving towards exploitation, first compile the exploit as before.
Now we run the exploit with a SUID of any choice. The /bin/su is a good SUID to target.
Mitigation
Patched versions of the Linux Kernel have been released for supported major kernel specifically, the vulnerability has been patched in Linux kernel versions 5.16.11, 5.15.25 and 5.10.102.Ensure that you apply updates to all of your Linux devices Hope you enjoyed reading it :)
Last updated