ADPWD-006: Account Lockout Policy
- Platform
- Active Directory
- Category
- AD Password & Lockout Policies
- Severity
- High
- Zero Trust pillar
- Identity (weight 2)
- Golden fixtures
- 3
- Branch coverage
- Observed: fixtures prove the verdicts they exercise
- Provenance
- baseline
What it checks
The check binds to the domain naming context (DC=...) and reads three attributes that live directly on the domainDNS object: lockoutThreshold (REG_DWORD-style integer, number of bad password attempts before lockout), lockoutDuration (Interval / LargeInteger expressed as negative 100-nanosecond ticks, how long the account stays locked), and lockOutObservationWindow (Interval, the rolling window over which bad attempts accumulate). Guerrilla converts the Interval values to minutes and fails when lockoutThreshold = 0 (lockout disabled outright), when lockoutThreshold > 10 (too permissive for spray defense), when lockoutDuration < 15 minutes, or when lockOutObservationWindow < 15 minutes. Fine-Grained Password Policies (FGPP, stored under CN=Password Settings Container,CN=System,DC=...) are enumerated separately and their msDS-LockoutThreshold, msDS-LockoutDuration, and msDS-LockoutObservationWindow values are checked against the same thresholds for any PSO that applies to a privileged group.
Why it matters
Without account lockout, an attacker can issue an unlimited stream of Kerberos AS-REQ or NTLM authentication attempts against the domain controller and never trigger a defensive response beyond log noise. Password spraying tools (Kerbrute, DomainPasswordSpray, MailSniper, TrevorSpray) are explicitly designed for this scenario: one or two guesses per account, rotated across the full user list, repeated daily. With lockoutThreshold = 0 the only thing stopping the attack is the attacker getting bored or the defender noticing the 4625 / 4771 event volume. The blast radius is the entire domain user population, including service accounts and break-glass administrators, because lockout policy is a single, domain-wide setting and applies to every account that does not have an overriding FGPP. The opposite failure mode also matters: a threshold of 3 with a 24 hour duration is trivially weaponized into a denial of service against the workforce, where an attacker who has only an internal foothold and a username list can lock out every account in the domain in minutes (a tactic Mandiant has reported in ransomware staging).
Attack path
Stage 1, recon: the attacker enumerates valid usernames from a public source (LinkedIn scrape, leaked breach corpus, anonymous LDAP query against a domain controller if 389/TCP is reachable, or a Kerbrute user enumeration that reads KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN versus KRB5KDC_ERR_PREAUTH_REQUIRED responses). Stage 2, policy probe: the attacker either reads the domain password policy with a low-privilege account (Get-ADDefaultDomainPasswordPolicy, or net accounts /domain) or infers the lockoutThreshold empirically by burning one or two known-bad attempts against a throwaway account. Stage 3, spray: the attacker runs Kerbrute passwordspray or DomainPasswordSpray with a curated password list (Season + Year, Company + 1, Welcome + Year) at a rate just below the threshold and outside the observation window, typically one attempt per account every 30 to 60 minutes. With lockoutThreshold = 0, the attacker skips stage 2 and 3 throttling entirely and runs at line speed. Successful credentials are then used for SMB or RDP lateral movement, or for AzureAD / Entra federated authentication if Seamless SSO or PHS is configured (Nestori Syynimaa has documented this exact path against hybrid tenants).
How Guerrilla assesses it
Guerrilla queries the domain root object via the existing AD PowerShell session, requesting lockoutThreshold, lockoutDuration, and lockOutObservationWindow. The Interval attributes are converted from Windows FILETIME ticks (negative 100-ns intervals) to TimeSpan and reported in minutes. The check then enumerates Fine-Grained Password Policy objects (objectClass = msDS-PasswordSettings) under CN=Password Settings Container and reads their msDS-LockoutThreshold, msDS-LockoutDuration, msDS-LockoutObservationWindow, and msDS-PSOAppliesTo values to surface any PSO that weakens lockout for a privileged group. Findings are graded as Fail when threshold = 0, Warn when threshold > 10 or duration < 15 minutes, and Pass when all three values fall in the recommended range. Companion telemetry (Event ID 4740 on the PDC Emulator, account lockouts) is referenced in the report so the operator can correlate any current spray activity.
Recommended value
Account lockout threshold: 5-10 attempts. Lockout duration: 15-30 minutes. Reset counter after: 15-30 minutes
Remediation
Configure account lockout in Default Domain Policy: Computer Configuration > Policies > Windows Settings > Security Settings > Account Policies > Account Lockout Policy. Set threshold to 5-10 attempts, duration to 15-30 minutes, and observation window to 15-30 minutes. Monitor for lockout events that may indicate attacks
Fixture-proven verdicts
Every verdict below is proven by a golden fixture in the module's gating test suite. This table derives from the last green run; it cannot be edited by hand.
| Scenario | Expected verdict |
|---|---|
| clean | PASS |
| known-bad | FAIL |
| throttled | Not Assessed |
Framework mappings
- NIST SP 800-53
- AC-7
- CIS Benchmark
- 1.2.1, 1.2.2, 1.2.3
- ANSSI
- R35
- CIS AD Benchmark
- 5.3.1
- MITRE ATT&CK
- T1110.001, T1110.003