Lab Walkthrough - Heap-Based Buffer Overflow in Sudo (Baron Samedit)
In our lab walkthrough series, we go through selected lab exercises on our INE Platform. Subscribe or sign up for a 7-day, risk-free trial with INE and access this lab and a robust library covering the latest in Cyber Security, Networking, Cloud, and Data Science!
In this lab walkthrough, learn how to exploit the Heap-Based Buffer Overflow in Sudo aka Baron Samedit vulnerability (CVE-2021-3156).
What is sudo?
Sudo is a program designed to allow a sysadmin to give limited root privileges to users and log root activity. The basic philosophy is to give as few privileges as possible but still allow people to get their work done.
Github: https://github.com/sudo-project/sudo
For more information, please visit: https://www.sudo.ws/about/intro/
Technical difficulty: Beginner
Description
A Debian instance vulnerable to CVE-2021-3156: Heap-Based Buffer Overflow in Sudo (Baron Samedit) is provided to you. You would have access to regular user Alice.
This exercise will help you understand how to exploit a heap-based buffer overflow in Sudo.
Lab Environment
The user will get access to a Debian OS instance in this lab environment.
Goal after completing this scenario: Gain the root privileges by exploiting the sudo and read the flag, i.e., /root/FLAG1
Tools
The best tools for this lab are:
- make
- bash
- perl
- sudoedit
Lab Link:
Solution
Step 1: Open the lab link to access the Debian instance.
Debian Instance
We can notice that we are logged in as an Alice user on the machine.
Step 2: Now, let's try to read the /etc/shadow file using the current user, i.e Alice
This is the file where all user's hashes are stored /etc/shadow. We need root privileges to read this file.
Command:
cat /etc/shadow
We are expected to be unable to read this file because we do not have sufficient privileges.
Regular users can use the sudo command to read sensitive files to gain root privileges. The sudo command provides a mechanism for granting administrator privileges to regular users.
There are two ways to allow regular users to use the sudo command and gain root privilege.
- Editing the /etc/sudoers file
- Adding a user to the sudo group
Both the above operations require root privileges.
Step 3: Let's identify the sudo version.
Command:
sudo -V
We can notice that the sudo version is 1.8.27. We can search on Google to find vulnerabilities in this specific version.
We notice that the current version of sudo is vulnerable to privilege escalation and its registered CVE is CVE-2021-3156.
Sudo before 1.9.5p2 contains an off-by-one error that can result in a heap-based buffer overflow, which allows privilege escalation to root via "sudoedit -s" and a command-line argument that ends with a single backslash character.
Source: https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-3156
The Qualys Research Team has discovered a heap overflow vulnerability in sudo, a near-ubiquitous utility available on major Unix-like operating systems. Any unprivileged user can gain root privileges on a vulnerable host using a default sudo configuration by exploiting this vulnerability.
The vulnerable code: https://github.com/sudo-project/sudo/commit/8255ed69
/* Alloc and build up user_args. */
for (size = 0, av = NewArgv + 1; *av; av++)
size += strlen(*av) + 1;
user_args = emalloc(size);
if (ISSET(sudo_mode, MODE_SHELL|MODE_LOGIN_SHELL)) {
/*
* When running a command via a shell, the sudo front-end
* escapes potential meta chars. We unescape non-spaces
* for sudoers matching and logging purposes.
*/
for (to = user_args, av = NewArgv + 1; (from = *av); av++) {
while (*from) {
if (from[0] == '\\' && !isspace((unsigned char)from[1]))
from++;
*to++ = *from++;
}
*to++ = ' ';
}
*--to = '\0';
} else {
for (to = user_args, av = NewArgv + 1; *av; av++) {
n = strlcpy(to, *av, size - (to - user_args));
if (n = size - (to - user_args))
errorx(1, _("internal error, set_cmnd() overflow"));
to += n;
*to++ = ' ';
}
*--to = '\0';
}
}
}
The attacker can control the size of the user_args buffer that can be overflowed; we can notice at the code line numbers: [868-870]
Source: https://blog.qualys.com/vulnerabilities-threat-research/2021/01/26/cve-2021-3156-heap-based-buffer-overflow-in-sudo-baron-samedit
This vulnerability triggers many obvious questions about why it took almost ten years to find this bug when the source code is already available to the public. The code was committed on Jul 29, 2011 by Todd C. Miller. Was it tough to find the bug, or did nobody try it?
Originally this vulnerability was discovered by Qualys Security Research Team.
Here is the excellent interview of the guy who is part of the security research team at Qualys that discovered the heap overflow vulnerability in sudo.
Also, take a look at this awesome video explaining CVE-2021-3156 Baron Samedit, created by LiveOverFlow.com.
He even contacted Qualys Research Team to know about this finding, and they shared the following insight:
When we audit code, we completely open our minds: anything that differs from the program's or programmer's expectations is exciting or may become interesting at some point, i.e., any kind of bugs and weirdness.
And going into more detail about the actual discovery of the vulnerability:
a/ noticing that the loop in set_cmnd() may increment a pointer out of bounds;
b/ realizing that this should be impossible because of parse_args()'sescaping;
c/ looking for ways to bypass this escaping and discovering the sudoedit trick.
Source: https://liveoverflow.com/critical-sudo-vulnerability-walkthrough-cve-2021-3156/
Now, the quick question is, how do we find this bug using open source fuzzers? We need to understand that it wasn't an easy job. Many people must have fuzzed all the Linux binaries to find this type of bug. But, we need some extra modification in the fuzzer to detect this crash. milek7 did a great job of analyzing the vulnerability and showing how fuzzing is done using American Fuzzy Lop, i.e., AFL++ to discover this bug.
Now, let's jump on the lab and exploit it.
Step 4: We will quickly try the available PoC.
Before, we jump and overflow the sudo manually. Let's first understand that sudoedit is part of sudo.
sudoedit is the utility that allows regular users to edit files. We can use the sudo -e command or sudoedit <file for modifying the file. These commands only work, If the policy authorizes the user.
The sudoedit is a symlink to the sudo binary. We can confirm by running the ls command.
Commands:
whereis sudoedit
ls -lah /usr/bin/sudoedit
Step 5: Now, let's perform a quick PoC for CVE-2021-3156.
Command:
sudoedit -s 'INEINEINEINEINE\'
Command:
sudoedit -s '\' `perl -e 'print "A" x 65536'`
That's it. It's that simple. :) The above commands demonstrate the buffer overflow.
Now, the quick question. Can't we use sudo instead of sudoedit?
The answer is No! Both have different functions to handle this and editing operations, so we can't run fuzzer on sudo; it won't give us any positive output.
Step 6: Now, let's go ahead and exploit the vulnerability.
The full PoC of this vulnerability is provided in the /home/alice/CVE-2021-3156 directory.
The sudo heap overflow exploits were developed by 0xdevil.
For detailed information about how the exploit is written, we can refer to this excellent blog written by 0xdevil.
First, let's run the make command and create an executable from exploit.c and shared library from libnss_XXXXXXX/XXXXXX.c source code.
Commands:
cd /home/alice/CVE-2021-3156/
make
file libnss_XXXXXXX/XXXXXX.so.2
file exploit
We have successfully generated two files. Now, executing the exploit would hijack the library and give us the root shell.
Also, we can't run the exploit executable directly it will throw a Segmentation fault error message.
The author mentioned the reason below:
Now, because of slight differences in the heap layout from system to system, we cannot hard code sizes in our exploit. For example, another Debian 10 might require a different ENVP_SIZE size and/or a different LC_SIZE, I did some tests and found a pattern that works for multiple systems. Bruteforcing will be required to find the right combinations of sizes.
So, the exploit (exploit.c) executable also accepts the lc_size and envp_size argument. There is one bash file that will find a valid pattern and run the exploit executable. Once it works, we would have the root shell.
Step 7: We will run the exploit.sh script to gain root access.
Before we move, let's make the exploit.sh script executable.
Commands:
chmod +x exploit.sh
ls
Now, we are all set to run the exploit and bash script.
Commands:
./exploit.sh 2/dev/null
id
whoami
Step 8: Now, let's read the flag.
Commands:
bash
ls /root
cat /root/FLAG1
The Flag is: 7e9b2ed1272331cfbd2aac2e5eb3f84b
We have gained a shell with user root.
In this manner, an attacker can exploit Baron Samedit vulnerability to perform privilege escalation.
Conclusion:
After doing this exercise, we must keep the production system updated. Keep an eye on the new CVEs' high severity vulnerabilities. Avoid giving access to the sensitive server. Even with the low-privileged user. Also, try to fix the issue by the patch or using the MITRE advisories.
There are still many questions related to this vulnerability. The bug was there for almost ten years, and nobody noticed it, or it was widely exploited by the attackers. The answers to these questions are challenging to find. However, we know that no system or application is secure. Here, we have to build a good SOC (Security operations center) so that you can catch an attacker and prevent more damage even in the worst case.
References
3. Baron Samedit CVE-2021-3156
4. Qualys
Try this exploit for yourself! Subscribe or sign up for a 7-day, risk-free trial with INE to access this lab and a robust library covering the latest in Cyber Security, Networking, Cloud, and Data Science!