On March 7, 2022, Security researcher Max Kellerman disclosed ‘Dirty Pipe’ - a Linux local privilege escalation vulnerability, plus a proof of concept on how to exploit it. The vulnerability affects the Linux Kernel and allows users with low privileges to overwrite read-only files in versions 5.8 and later, plus Android devices.
CVE ID: CVE-2022-0847
CVSS Score: 7.8
Here are some terms you should be familiar with to understand the Dirty Pipe vulnerability:
- Page Cache: Whenever a file is read or written, the data is put into the page cache to avoid expensive disk access due to subsequent read/write. If the data inside the cache is altered from what is on the disk, the page is known to have become ‘dirty’.
- Pipe: A data channel used for communication between two processes in the Linux OS.
- Pipe Flag: These specify the permissions for the data present in the pipe. One of those flags is ‘PIPE_BUF__FLAG_CAN_MERGE’ which indicates that the data inside the pipe can merge.
- Splice(): A system call introduced in Linux 2.6.16 which moves the data between pipes and file descriptors without user interaction.
WHERE IS THE VULNERABILITY PRESENT?
The Dirty Pipe vulnerability arises because of how the kernel implements the pipes. There was an addition of a new flag, ‘PIPE_BUF_FLAG_CAN_MERGE’, when Linux kernel v5.8 was introduced in 2020. The use of this flag is to tell the kernel to update the page without forcing a rewrite of the data. In addition, there is a bug in Linux kernel v4.9, released in 2016, allowing pipes to be created with arbitrary flags. Splice, a functionality of the kernel that provides a system call, pushes the file contents into a pipe. This system call allows us to point pipes at page buffers.
For the exploit to work, the user must have read permission of the target file (for example, /etc/passwd file).. When the following process flow of the exploit code takes place:
- It opens the target file with the read only flag.
- The exploit then runs and adds the “PIPE_BUF_FLAG_CAN_MERGE” flag.
- Followed by this, it makes use of splice() to point the pipe at a particular section of the target file.
- Then, it overwrites the data that is pushed into the pipe or specified by the user in the pipe with the help of the “PIPE_BUF_FLAG_CAN_MERGE” flag.
VULNERABLE APP AND EXPLOITATION
Reference link: - https://tryhackme.com/room/dirtypipe
Exploitation Method 1
The exploit code used can be found here. It hosts Max Kellerman's original proof of concept exploit code plus a detailed explanation of the Dirty Pipe vulnerability.
To run the exploit code we need to explicitly define the file we want to overwrite - the offset point from which we have to overwrite and the content we want to insert. In our case, we want to insert our newly created user into the /etc/passwd file.
Steps for exploitation:
STEP 1: Generate the password hash using OpenSSL to create a SHA512Crypt hash of your chosen password. This enables us to add the newly created user’s credentials into the /etc/passwd file in a valid format.
> openssl passwd -6 –salt test “password”
The valid user entry into the /etc/passwd file should look something like this:
STEP 2: Overwrite the user entry into the /etc/passwd file. By doing this, we create or overwrite a user, “safesecurity”, with root permissions (/bin/bash) and a known password hash directly into the passwd file. Paste the newly-created user’s entry into the passwd file as shown below, and save it.
STEP 3: Run the grep command with -b flag to find the offset of “games” from the beginning of the file. The output displays that the offset is 189. The offset is where the exploit should begin writing from within the file. Now we are ready to run the exploit.
> grep -b games /etc/passwd
STEP 4: Compile the exploit code using gcc.
> gcc poc.c -o exploit
The following steps explain what the exploit code actually does
- Firstly, it creates a pipe.
- It fills the pipe with arbitrary data and sets the PIPE_BUF_FLAG_CAN_MERGE flag.
- Drains the data of the pipe
- Splices data from the target file into the pipe from just before the target offset with the help of a splice () function.
- Finally, it writes the arbitrary data into the pipe that will eventually overwrite the cached file page.
STEP 5: Execute the following command to copy the passwd file to /tmp and then execute the exploit code.
> cp /etc/passwd /tmp/passwd
The following exhibit shows the privileges before running the exploit code.
STEP 6: Run the exploit along with the offset value that we obtained previously and the newly-created user’s passwd file entry. The command should use the following format:
> ./exploit /etc/passwd 189 'USERNAME:HASH:0:0::/root:/bin/bash
The following exhibit displays that the root privileges have been attained.
Exploitation Method 2
This is another way of abusing the arbitrary file write vulnerability. The exploit code used below is written by Bl4sty and can be accessed via this link. Instead of overwriting the /etc/passwd file, the exploit code overwrites a user-specified SUID binary (“/bin/sh”, in our case). It injects the shellcode into this binary then executes it with the permissions of a privileged user such as ‘root’. The exploit code performs the hijack of the chosen SUID binary and lets it create a backdoor binary in the /tmp directory, having the SUID bit, and then calls /bin/sh. After this, the targeted SUID binary is restored by adding the overwritten section again and then the created backdoor is used to grant the attacker with the ‘shell as a privileged user or root’. This exploitation technique is also known as SUID binary hijacking.
Steps for exploitation:
STEP 1: Run the below command to print the SUID executables.
> find / -type f -user root -perm /4000 2>/dev/null
Bl4sty wrote an improved version of the exploit (if compared with Kellerman’s exploit) that makes attaining root or higher privileges easier by altering the /usr/bin/su command to dump a root shell at /tmp/sh and then executing the script.
STEP 2: Compile the exploit, and execute it on one of the SUID executables that we discovered for example, “/bin/su”, to obtain the root privileges.
> gcc dirtypipez.c -o exploit
> ./exploit /bin/su
Using the Dirty Pipe vulnerability, we can easily overwrite any file that has read-only permissions. One thing to keep in mind is that changes made by the exploit will not be restored after we reboot/restart the system and that the system memory will revert to the original file content.
DETECTION OF THIS VULNERABILITY
To detect if an application is vulnerable or not, run the following command in the Linux CLI by verifying the Linux kernel version:
> uname -srm
The endpoints running Linux affected by this vulnerability have a kernel version of 5.8 or higher until any version before 5.16.11, 5.15.25, and 5.10.102.
Simply update the kernel to a patched version - v5.16.11, 5.15.25 and 5.10.102. Run an update with your distro’s package manager to upgrade to the latest kernel.