Attacks
Sudo heap overflow: Replicating CVE-2021-3156 with AFL

VP of Hacking
Updated
Feb 1, 2021
5 min
On January 26 of 2021, Qualys published a new vulnerability discovered on sudo
, a tool used to perform actions as other users (most commonly as root
) on Linux-based systems.
Although Qualys provided a very good analysis of the vulnerability, they didn’t state how they found it.
In this post, we will show a way to discover this kind of bugs using AFL++, a community-fork of American Fuzzy Lop, a fuzzer that uses compile-time instrumentation and genetic algorithms to find, among other things, security bugs.
Preparing the environment
First, we need to install AFL
. You just have to clone the repo and follow the instructions. The only necessary change I made was to specify a version for the libstdc++-dev
package. It needs to be the same as the gcc
compiler on your system:
And check the installation with:
Now, we need to download one of the affected versions of sudo
. We will use 1.9.5p1
.
That’s it, we have everything we need!
Patching sudo for fuzzing purposes
AFL
uses instrumented fuzzing only on binaries built with their compilers. Instrumented mode helps AFL
perform coverage-guided fuzzing and generate mutating input based on the measured behavior of previous payloads.
However, AFL
will expect parameters from the standard input and files only.
sudo
uses command-line arguments, which is not compatible with AFL
. However, there is a way provided by AFL
to fuzz that kind of binaries: A C
header that converts a standard input payload to argv[]
parameters.
To do that, we just need to:
Copy the
AFLplusplus/utils/argv_fuzzing/argv-fuzz-inl.h
file to the main source ofsudo
.Modify the
main()
function ofsudo
to call theAFL_INIT_ARGV()
macro.
This will work by converting all the expected argv[]
array from standard input with parameters separated by a \0
byte and terminating the array with a \0\0
.
We also need to disable the sudo
password prompt; otherwise, the fuzzing will hang.
Now, we can build our patched sudo
. As it needs to be built with AFL
compilers, we must overwrite the CC
environment variable. We may also want to enable debugging symbols, and finally we should install it on a isolated path so we can safely remove it when we finish our fuzzing session. We can do that by issuing:
This will install our modified sudo
on /fuzz/sudo
. To check that our installation worked, along with the patches, just type:
Great, now it’s fuzzing time!
Fuzzing sudo
When using AFL
, I recommend having a separate directory on which you can store the inputs and outputs for each fuzzed binary. I will create mine at $HOME/fuzz/sudo
.
The output
directory will be on where AFL
will store the fuzzing state. As this directory will be extensively written to, it is recommended to use a RAM-based filesystem to improve performance and avoid damaging SSD
disks.
In the input
directory, we will create initial payloads for sudo
:
Fuzzing is CPU-intensive, but you can use parallel fuzzing with AFL
. I used an 8-core PC and launched a Master
AFL
instance:
And launched 6 Slave
instances on different consoles:
It looked like this:

And just after a few minutes of fuzzing, one of the slaves showed 3 crashes!

You can find here the payloads that caused the crashes:
If we examine the contents of these payloads, we can see that they all invoked sudoedit
with the -s
and -i
flags. AFL
mutated the original input payloads and eventually triggered the bug found by Qualys.

We can also replicate the crash by simply passing the offending payloads to our sudo
:
And you can use GDB
to start the exploitation process:

Conclusion
It is easy to find crashes on software using AFL
if you have the source code. What is unbelievable is that it took 10 years for a bug like this to be found on sudo
!
Get started with Fluid Attacks' PTaaS right now
Related posts