Release Date:
January 30, 2020 (updated February 5, 2020 with additional exploitation details)
Summary:
Sudo's
pwfeedback option can be used to provide visual
feedback when the user is inputting their password. For each key
press, an asterisk is printed. This option was added in response
to user confusion over how the standard
Password: prompt
disables the echoing of key presses. While
pwfeedback is
not enabled by default in the upstream version of sudo, some systems,
such as Linux Mint and Elementary OS, do enable it in their default
sudoers files.
Due to a bug, when the pwfeedback option is enabled in the
sudoers file, a user may be able to trigger a stack-based buffer overflow.
This bug can be triggered even by users not listed in the sudoers file.
There is no impact unless pwfeedback has
been enabled.
Sudo versions affected:
Sudo versions 1.7.1 to 1.8.30 inclusive are affected but only if the
pwfeedback option is enabled in sudoers. It was originally
thought to not be exploitable in sudo versions 1.8.26 through 1.8.30
but that has been shown to not be the case.
A user with sudo privileges can check whether pwfeedback
is enabled by running:
sudo -l
If
pwfeedback is listed in the "Matching Defaults entries"
output, the sudoers configuration is affected. In the following
example, the sudoers configuration is vulnerable:
$ sudo -l
Matching Defaults entries for millert on linux-build:
insults, pwfeedback, mail_badpass, mailerpath=/usr/sbin/sendmail
User millert may run the following commands on linux-build:
(ALL : ALL) ALL
CVE ID:
This vulnerability has been assigned
CVE-2019-18634
in the
Common
Vulnerabilities and Exposures database.
Details:
Exploiting the bug does not require sudo permissions, merely that
pwfeedback be enabled. The bug can be reproduced by passing
a large input with embedded terminal kill characters to sudo from
a pseudo-terminal that cannot be written to. For example, using
the socat utility and assuming the terminal kill character is set
to control-U (0x15):
$ socat pty,link=/tmp/pty,waitslave exec:"perl -e 'print((\"A\" x 100 . chr(0x15)) x 50)'" &
$ sudo -S -k id < /tmp/pty
Password: Segmentation fault (core dumped)
For sudo versions prior to 1.8.26, and on systems with uni-directional
pipes, reproducing the bug is simpler. Here, the terminal kill
character is set to the NUL character (0x00) since sudo is not
reading from a terminal. This method is not effective in newer
versions of sudo due to a change in EOF handling introduced in
1.8.26.
$ perl -e 'print(("A" x 100 . chr(0)) x 50)' | sudo -S -k id
Password: Segmentation fault (core dumped)
There are two flaws that contribute to this vulnerability:
- The pwfeedback option is not ignored, as it should be,
when reading from something other than the user's terminal,
/dev/tty. The use of the -S option should
effectively disable pwfeedback.
- The code that erases the line of asterisks does not
properly reset the buffer position if there is a write
error, but it does reset the remaining buffer length.
As a result, the getln() function can write past the
end of the buffer, leading to an overflow.
If the user can cause sudo to receive a write error when it attempts
to erase the line of asterisks, the bug can be triggered. Because
the remaining buffer length is not reset correctly on write error
when the line is erased, a buffer on the stack can be overflowed.
Impact:
There is
no impact unless
pwfeedback has
been enabled in the sudoers file.
If pwfeedback is enabled in sudoers, the stack overflow
may allow unprivileged users to escalate to the root account.
Because the attacker has complete control of the data used to
overflow the buffer, there is a high likelihood of exploitability.
Workaround:
If the sudoers file has
pwfeedback enabled, disabling it
by pre-pending an exclamation point is sufficient to prevent
exploitation of the bug. For example, change:
Defaults pwfeedback
To:
Defaults !pwfeedback
After disabling
pwfeedback in sudoers using the visudo
command, the example
sudo -l output becomes:
$ sudo -l
Matching Defaults entries for millert on linux-build:
insults, mail_badpass, mailerpath=/usr/sbin/sendmail
User millert may run the following commands on linux-build:
(ALL : ALL) ALL
Fix:
The bug is fixed in sudo 1.8.31.
Credit:
Joe Vennix from Apple Information Security found and analyzed the
bug.
William Bowling reported a way to exploit the bug in sudo 1.8.26
though 1.8.30.