Authored by Qualys Security Advisory

Qualys has released extensive research details regarding a heap-based buffer overflow vulnerability in sudo. The issue was introduced in July 2011 (commit 8255ed69), and affects all legacy versions from 1.8.2 to 1.8.31p2 and all stable versions from 1.9.0 to 1.9.5p1, in their default configuration.

advisories | CVE-2021-3156


Qualys Security Advisory

Baron Samedit: Heap-based buffer overflow in Sudo (CVE-2021-3156)


========================================================================
Contents
========================================================================

Summary
Analysis
Exploitation
Acknowledgments
Timeline


========================================================================
Summary
========================================================================

We discovered a heap-based buffer overflow in Sudo
(https://www.sudo.ws/). This vulnerability:

- is exploitable by any local user (normal users and system users,
sudoers and non-sudoers), without authentication (i.e., the attacker
does not need to know the user's password);

- was introduced in July 2011 (commit 8255ed69), and affects all legacy
versions from 1.8.2 to 1.8.31p2 and all stable versions from 1.9.0 to
1.9.5p1, in their default configuration.

We developed three different exploits for this vulnerability, and
obtained full root privileges on Ubuntu 20.04 (Sudo 1.8.31), Debian 10
(Sudo 1.8.27), and Fedora 33 (Sudo 1.9.2). Other operating systems and
distributions are probably also exploitable.


========================================================================
Analysis
========================================================================

If Sudo is executed to run a command in "shell" mode (shell -c command):

- either through the -s option, which sets Sudo's MODE_SHELL flag;

- or through the -i option, which sets Sudo's MODE_SHELL and
MODE_LOGIN_SHELL flags;

then, at the beginning of Sudo's main(), parse_args() rewrites argv
(lines 609-617), by concatenating all command-line arguments (lines
587-595) and by escaping all meta-characters with backslashes (lines
590-591):

------------------------------------------------------------------------
571 if (ISSET(mode, MODE_RUN) && ISSET(flags, MODE_SHELL)) {
572 char **av, *cmnd = NULL;
573 int ac = 1;
...
581 cmnd = dst = reallocarray(NULL, cmnd_size, 2);
...
587 for (av = argv; *av != NULL; av++) {
588 for (src = *av; *src != '