Password Guessing
Adversaries with no prior knowledge of legitimate credentials within the system or environment may guess passwords to attempt access to accounts. Without knowledge of the password for an account, an adversary may opt to systematically guess the password using a repetitive or iterative mechanism. An adversary may guess login credentials without prior knowledge of system or environment passwords during an operation by using a list of common passwords. Password guessing may or may not take into account the target's policies on password complexity or use policies that may lock accounts out after a number of failed attempts. Commonly targeted services include SSH, RDP, SMB, LDAP, Kerberos, FTP, MSSQL, MySQL, VNC, and web management portals. Threat actors such as APT28, APT29, Emotet, and tools like CrackMapExec have leveraged this technique extensively.
// T1110.001 - Password Guessing Detection
// Detect high-volume authentication failures indicative of password guessing
let TimeWindow = 10m;
let FailureThreshold = 10;
let AccountLockoutThreshold = 5;
// --- Windows Security Event Logon Failures (Event ID 4625) ---
let WindowsLogonFailures =
SecurityEvent
| where TimeGenerated > ago(1h)
| where EventID == 4625
| where AccountType == "User"
| extend TargetAccount = tolower(TargetUserName)
| extend SourceIP = IpAddress
| where TargetAccount !in~ ("anonymous logon", "-", "")
| where SourceIP !in ("127.0.0.1", "::1", "-", "")
| summarize
FailureCount = count(),
DistinctAccounts = dcount(TargetAccount),
Accounts = make_set(TargetAccount, 20),
LogonTypes = make_set(LogonType),
FirstSeen = min(TimeGenerated),
LastSeen = max(TimeGenerated)
by SourceIP, Computer, bin(TimeGenerated, TimeWindow)
| where FailureCount >= FailureThreshold
| extend DetectionType = "Windows Logon Failure Burst"
| extend Severity = case(
FailureCount >= 50, "High",
FailureCount >= 20, "Medium",
"Low"
);
// --- Kerberos Pre-Auth Failures (Event ID 4771) ---
let KerberosFailures =
SecurityEvent
| where TimeGenerated > ago(1h)
| where EventID == 4771
| extend TargetAccount = tolower(TargetUserName)
| extend SourceIP = IpAddress
| where TargetAccount !in~ ("-", "")
| summarize
FailureCount = count(),
DistinctAccounts = dcount(TargetAccount),
Accounts = make_set(TargetAccount, 20),
FirstSeen = min(TimeGenerated),
LastSeen = max(TimeGenerated)
by SourceIP, Computer, bin(TimeGenerated, TimeWindow)
| where FailureCount >= FailureThreshold
| extend DetectionType = "Kerberos Pre-Auth Failure Burst"
| extend LogonTypes = dynamic([])
| extend Severity = case(
FailureCount >= 50, "High",
FailureCount >= 20, "Medium",
"Low"
);
// --- NTLM Authentication Failures (Event ID 4776) ---
let NTLMFailures =
SecurityEvent
| where TimeGenerated > ago(1h)
| where EventID == 4776
| where Status != "0x0"
| extend TargetAccount = tolower(TargetUserName)
| extend SourceIP = SourceWorkstation
| where TargetAccount !in~ ("-", "")
| summarize
FailureCount = count(),
DistinctAccounts = dcount(TargetAccount),
Accounts = make_set(TargetAccount, 20),
FirstSeen = min(TimeGenerated),
LastSeen = max(TimeGenerated)
by SourceIP, Computer, bin(TimeGenerated, TimeWindow)
| where FailureCount >= FailureThreshold
| extend DetectionType = "NTLM Auth Failure Burst"
| extend LogonTypes = dynamic([])
| extend Severity = case(
FailureCount >= 50, "High",
FailureCount >= 20, "Medium",
"Low"
);
// --- Union all detection types ---
union WindowsLogonFailures, KerberosFailures, NTLMFailures
| project
TimeGenerated = FirstSeen,
LastSeen,
Computer,
SourceIP,
DetectionType,
FailureCount,
DistinctAccounts,
Accounts,
LogonTypes,
Severity
| sort by FailureCount desc Data Sources
Required Tables
False Positives
- Misconfigured service accounts with expired or incorrect passwords generating repeated authentication failures against domain controllers
- Vulnerability scanners or penetration testing tools (Nessus, Qualys, Rapid7) performing authenticated scans that fail due to incorrect test credentials
- End users who have forgotten their passwords attempting to log in multiple times before calling the help desk
- Automated IT processes or scripts using hardcoded credentials that have not been updated after a password rotation
References (13)
- https://attack.mitre.org/techniques/T1110/001/
- https://learn.microsoft.com/en-us/windows/security/threat-protection/auditing/event-4625
- https://learn.microsoft.com/en-us/windows/security/threat-protection/auditing/event-4771
- https://learn.microsoft.com/en-us/windows/security/threat-protection/auditing/event-4776
- https://learn.microsoft.com/en-us/windows/security/threat-protection/auditing/event-4740
- https://www.microsoft.com/en-us/security/blog/2020/09/10/strontium-new-campaign/
- https://github.com/redcanaryco/atomic-red-team/blob/master/atomics/T1110.001/T1110.001.md
- https://github.com/dafthack/MSOLSpray
- https://github.com/byt3bl33d3r/CrackMapExec
- https://www.us-cert.gov/ncas/alerts/TA18-086A
- https://web.archive.org/web/20200302085133/https://www.cylance.com/content/dam/cylance/pages/operation-cleaver/Cylance_Operation_Cleaver_Report.pdf
- https://www.trendmicro.com/vinfo/us/security/news/cybercrime-and-digital-threats/emotet-now-spreads-via-wi-fi
- https://www.mandiant.com/resources/blog/apt29-microsoft-365
Unlock Pro Content
Get the full detection package for T1110.001 including response playbook, investigation guide, and atomic red team tests.