Linux Privilege Escalation – Using apt-get/apt/dpkg to abuse sudo “NOPASSWD” misconfiguration

(PART TWO AT BOTTOM OF THE PAGE)
There are many well known and documented attack vectors for the sudo command that exist. Please see my Useful Resources page for the Windows & Linux Privilege Escalation piece that contains a ton of helpful knowledge in this category. Today, we’re going to be using a very poorly documented feature in apt-get when a normal user is allowed to execute apt-get as a root user. Let’s dive in!

(Please keep in mind these techniques are not exactly brand new, but are a fresh perspective on Linux priv-esc that you don’t see mentioned a lot of places at all.)

So, first and foremost, let’s take a look at a typical sudo misconfiguration. On any given misconfiguration in this category, you’re going to see something along the lines of this in your /etc/sudoers file. You may also obtain the output of what commands the user can run without a password by typing sudo -l as well. Either way, this is the offending configuration line.

*****
%whitehat       ALL= NOPASSWD: /usr/bin/apt-get
*****

We can easily see here that the user “whitehat” is only allowed to execute the command “apt-get”. This is presumably to allow a non-root user to perform updates on the machine, without giving the user full-on root access across the board. At least this was the intention – let’s take a look at the man page for apt-get to get a better understanding of why this is so dangerous. Keep in mind, this same technique is usable with APT-GET, APT, and DKPG across the board!

If you look at the very bottom, you’ll notice that there is an “-o” or “–option” flag that can be passed into apt-get. This allows us to set an “arbitrary configuration option”. In digging into the documentation further, I come across a series of configuration items available to the options parameter of the following kind.

*****
APT::Update::Pre-Invoke::
APT::Update::Post-Invoke::
DPkg::Pre-Invoke::

*****

Using these commands, we can actually execute an arbitrary command of our choosing (almost like adding && or | in Bash, except you’re specifying whether to perform the command prior to the update, after the update, or both.) In most cases of a privilege escalation, we’re looking to call /bin/sh or /bin/bash -i somehow. The syntax for such a command is included below:

*****
sudo apt-get update -o APT::Update::Pre-Invoke::=”/bin/bash -i”
*****

So, what happens when a user executes this command? Allow me to demonstrate. Please take specific note in the terminal for the “$” and the following “#” as to indicate the permissions of the user shell have changed.

As we can see, this made very quick work of taking a low privilege user with no read, write, or execute permissions outside of their home directory and a handful of others, and shooting them directly into a root Bash terminal. Simple! Let’s take a look at what the dpkg syntax may look like. In this example, we’ll be calling an arbitrary shell script of our choosing and running an arbitrary command. Simply place a file in /etc/apt/apt.conf.d/

*****
DPkg::Pre-Invoke {“/path/to/script”;};
DPkg::Pre-Invoke {“command”;}
DPkg::Post-Invoke {“command”;}
*****

Running any of those through dpkg using the same methods will return the desired output of elevating us to a root shell. One way you can partially defend against such a technique is to use regular expressions in your /etc/sudoers file to block my example above:

As we can see here, this did prevent my standard example from working. However, please keep in mind that using NOPASSWD in your /etc/sudoers file is DANGEROUS. If at any point one of these binaries manage to load an attack controller command, shell script, or other system function that allow execution of another command, this will most likely fall victim to the same issue.

In fact…in this particular case, we still have another binary “openresty”. Let’s take another look at that one again. We’re not quite done yet.

The Joys of Symbolic Links in Linux

So, there are NO restrictions on that “openresty” binary. Let’s take a look at what that binary’s permissions are…

So, this binary is world writable by any user on the filesystem. However, the openresty binary allowed in the /etc/sudoers file calls directly to this binary as a symbolic filesystem link. What happens if we’re to overwrite the binary with an attack controlled binary to execute?

So, we’ve again made quick work of a misconfiguration in sudoers that:
1. I had never seen before
2. Demonstrates the dangers of a user controlled value or binary in practice.


There were launch options in the openresty/nginx binary such as “-c” to load an arbitrary configuration script. This is also most likely an attack vector as well

Also, please be advised that if you allow DPKG to run sudo at ALL, you do run the risk of someone compiling their own malicious deb with a tool like FPM that makes it easy to compile your own simple .deb files. One example is as such:

root@855aa1793938:~# fpm -s dir -t deb –name sploit –before-install BS_package/foo.sh BS_package/

Loading this .deb into apt (which just runs echo) returns the following result
:

As we can see, the shell script hidden within our .deb executes with root permissions.
DebSploit In Action

In this particular misconfiguration, apt-get requires a “.” and a “/” to install a file locally. Due to the regex in the sudoers, this will not succeed. However, this still does not mean that this is safe. As you can see, it is trivial to get an attacker controlled .deb loaded into the installer in the event of an alphanumeric regex.

This was a great link for finding the DPKG syntax – man pages however are your best friend.

As a bonus, here are some other commands that can be used to do the same thing if allowed in your /etc/sudoers file to be ran with NOPASSWD

*****
/usr/bin/find
/usr/bin/nano
/usr/bin/vim

/usr/bin/vi
/usr/bin/ruby
/usr/bin/perl
/usr/bin/python
/usr/bin/man
/usr/bin/awk
/usr/bin/less
/usr/bin/nmap ( –interactive and –script method)
/bin/more
/usr/bin/wget
/usr/sbin/apache2

*****

These attack vectors are well documented online and examples are as well. Again, please see my Useful Resources page for more examples. There are ENDLESS examples possible with this sort of thing. Do NOT assume any given service is safe – ESPECIALLY things like scp, FTP clients, env.

Also, if the NOPASSWD command is ran on a command or shell script with read/write permissions, it’s trivial to replace said binary or compile your own malicious one in place and place it in the same path

***
Linux Privilege Escalation using Sudo Rights
***

So, what should we take away from this?

I think the biggest thing is simply the theory of least permission possible, like many other things. You want the absolute MINIMUM amount of commands available to be ran as root with no password possible. Otherwise, you’re going to be chasing the hypothetical dragon manually editing your sudoers file every time someone comes up with some creative Bash trick to re-route your allowed command to execute another arbitrary one.

One good takeaway from this is that package managers are a very undocumented realm in privilege escalation. I was not able to find a lot of other examples at all and MANY systems administrators (including several ones I know in the security field) have done NOPASSWD on their package managers and thought this was safe…

***
Here’s another resource as well on executing commands and shell scripts through package managers!

***

Thanks for reading. Now, go wild and find your own methods! USE THOSE MAN PAGES, DON’T BE LAZY WITH SUDOERS, AND LIMIT READ AND WRITE PERMISSIONS ON YOUR FILESYSTEM! PART TWO BELOW.

PART TWO WITH MORE PAYLOADS

6 thoughts on “Linux Privilege Escalation – Using apt-get/apt/dpkg to abuse sudo “NOPASSWD” misconfiguration

  1. Hi! I just wanted too ask if you ever have any
    problems with hackers? My last blog (wordpress) was hacked and
    I ended up loosing many months of hard work due to no backup.
    Do you have any solutions to stop hackers?

  2. Overall useful article pointing out some often-overlooked things. There’s just one minor oversight at the part where the openresty symlink is mentioned, though. It says that the binary is world-writable, but the article only shows the symlink’s 777 permissions – which are ignored. The link target’s permissions are what matter, and those permissions are not shown. 🙂

Leave a Reply to anon Cancel reply

Your email address will not be published. Required fields are marked *