Detecting Pass-the-Hash Attacks via NTLM Logon and Multi-Source Log Correlation
Theory
Why This Matters
Pass-the-Hash (PtH) allows an attacker to authenticate as a Windows user using only the NTLM password hash — without ever knowing the plaintext password. Tools like Mimikatz, Impacket's psexec.py, and CrackMapExec make PtH trivially easy to execute once a hash is retrieved from LSASS memory. PtH bypasses password complexity requirements entirely, and because the hash may remain valid for months, a single memory dump can grant persistent, quiet lateral movement across an entire domain. Detecting PtH in event logs before domain-level access is achieved is one of the highest-value SIEM detection scenarios.
Core Concept
NTLM authentication works by having the authenticating client prove knowledge of the NT hash of the user's password via a challenge-response exchange. The NT hash is derived as MD4(UTF-16LE(password)). In a PtH attack, the attacker supplies this hash directly to the NTLM authentication function, skipping the password-to-hash derivation step.
The key forensic signature in Windows event logs is a logon type 3 (network) authentication using the NTLM authentication package recorded in Event 4624, originating from a workstation that the legitimate user would not typically access or that is a known-bad host. Complementing this, Event 4776 records credential validation on the domain controller, showing the workstation name supplied during authentication.
Indicators that differentiate PtH from legitimate NTLM logon type 3: - Source workstation name in the event does not match the expected workstation for the user - Logon process = NtLmSsp with no corresponding Kerberos ticket request (Event 4769) — organisations with Kerberos-only policies will not see legitimate NTLM logon type 3 - Same NTLM hash used from multiple different source IPs within a short window (visible via network captures or EDR telemetry) - Odd hours or geographically impossible source for the account
Technical Deep-Dive
-- Splunk: detect NTLM logon type 3 from unexpected workstations
index=wineventlog EventCode=4624 Logon_Type=3 AuthenticationPackageName=NTLM
| stats count values(ComputerName) AS dest_hosts values(WorkstationName) AS src_workstations
earliest(_time) AS first_seen
BY TargetUserName IpAddress
| where count > 3 OR mvcount(dest_hosts) > 2
| eval suspicious = if(mvcount(dest_hosts) > 2, "MULTI-HOST-PtH", "REVIEW")
| sort -count
-- Splunk: correlate 4776 (credential validation) with 4624 on same target
index=wineventlog EventCode=4776
| eval dc_time = _time
| join type=inner TargetUserName [
search index=wineventlog EventCode=4624 Logon_Type=3 AuthenticationPackageName=NTLM
| rename Account_Name AS TargetUserName
]
| stats count BY TargetUserName WorkstationName IpAddress
| where count > 1
# Extract NTLM type-3 messages from a PCAP to identify PtH sessions
tshark -r lateral.pcap
-Y "ntlmssp.messagetype == 3"
-T fields
-e frame.time -e ip.src -e ip.dst
-e ntlmssp.auth.username -e ntlmssp.auth.domain
-e ntlmssp.auth.hostname
# Python: parse evtx JSON for 4624 NTLM events and group by account+hash proxy (workstation name)
import json
from collections import defaultdict
events = json.load(open("security_events.json"))
ntlm_logons = defaultdict(set)
for e in events:
if (e.get("EventID") == 4624
and e.get("LogonType") == "3"
and "NTLM" in e.get("AuthenticationPackageName", "")):
user = e.get("TargetUserName", "")
src = e.get("IpAddress", "")
dest = e.get("ComputerName", "")
ntlm_logons[user].add((src, dest))
for user, pairs in ntlm_logons.items():
sources = set(p[0] for p in pairs)
dests = set(p[1] for p in pairs)
if len(sources) > 1 or len(dests) > 2:
print(f"PtH CANDIDATE: {user}")
print(f" Sources : {sources}")
print(f" Dests : {dests}")
Analytical Methodology
- Query your SIEM for Event 4624 with LogonType=3 and AuthenticationPackageName=NTLM for the investigation window. In Kerberos-enabled domains, NTLM network logons for domain users are inherently suspicious.
- Group by TargetUserName and IpAddress. Flag any account authenticating via NTLM from more than one source IP, or to more than two destination hosts, within a 30-minute window.
- For each flagged account, retrieve Event 4776 records from domain controllers. Correlate the Workstation field in 4776 against the known workstations legitimately assigned to that user. Unexpected workstation names are strong PtH indicators.
- Pull network captures or NetFlow for the flagged source IP. Identify SMB (port 445) or RPC (port 135) connections from that IP to internal hosts. NTLM handshake type-3 messages in the PCAP confirm PtH tool usage.
- Check the source host's EDR telemetry for LSASS access events (Windows Event 4656/4663 on lsass.exe, or Sysmon Event 10). If LSASS was accessed by a non-system process shortly before the PtH events, credential dumping is confirmed.
- Assess the scope of access achieved: which destination hosts accepted the NTLM authentication and generated 4624 events. Determine if any of those hosts are privileged (domain controllers, admin workstations, file servers holding sensitive data).
- Identify the hash origin: which host was the patient-zero for credential dumping. This host will show an LSASS access event before any outbound PtH authentication occurs.
- Document: compromised account, hash source host, PtH source IP(s), all destination hosts accessed, timestamps, and any data access (4663 object access events) on destination hosts during the attacker's session.
Common Analytical Errors
- Dismissing NTLM as legacy-only: Many modern environments still use NTLM for local account authentication and workgroup resources. NTLM logon type 3 from a local account is not inherently PtH; focus on domain accounts using NTLM where Kerberos is available.
- Missing the null session: Some PtH tools open an initial null session (anonymous logon type 3) before the authenticated session. Event 4624 with account name "ANONYMOUS LOGON" immediately before a successful NTLM logon from the same IP is a PtH indicator.
- Overlooking pass-the-ticket: If the organisation has disabled NTLM, attackers pivot to Kerberos ticket abuse (pass-the-ticket, overpass-the-hash). Absence of NTLM events does not confirm absence of credential-based lateral movement.
- Failing to check 4776 on DCs: Event 4624 is recorded on the destination host. Event 4776 is recorded on the authenticating DC. Analysts who only query member servers miss the DC-side evidence.
NICE Framework Alignment
| Code | Work Role Knowledge / Skill / Task | Relevance |
|---|---|---|
| K0046 | Knowledge of intrusion detection methodologies | PtH detection requires understanding NTLM protocol flow to distinguish legitimate from attack traffic |
| K0145 | Knowledge of security event correlation tools | Multi-event correlation across 4624, 4776, and network telemetry in a SIEM |
| K0187 | Knowledge of file type abuse by adversaries | Mimikatz and credential dumpers are frequently obfuscated or packed to evade endpoint detection |
| S0047 | Skill in preserving evidence integrity | LSASS dump artefacts and NTLM capture files must be preserved with chain-of-custody documentation |
| T0049 | Decrypt seized data / analyze forensic artifacts | Cracking captured NTLMv2 challenge-response hashes to recover plaintext passwords for attribution |
Further Reading
- Gentilkiwi: Mimikatz documentation — understanding what sekurlsa::pth does and what it leaves behind
- Microsoft Security Advisory: Mitigating Pass-the-Hash and Other Credential Theft Techniques (v2)
- Impacket psexec.py source — study the tool's NTLM session setup to recognise its event log signature
- SANS: "Detecting Pass-the-Hash with Windows Event Logs" (blog post by Chad Tilbury)
- ATT&CK T1550.002: Pass the Hash — detection data sources and mitigation controls
Challenge Lab
Reinforce your learning with a hands-on generated challenge based on this card's competency.