ADPWD-004: Minimum Password Length
- 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 root via LDAP and reads the minPwdLength attribute on the domainDNS object (the default Domain Password Policy is stored directly on the domain head; it is not a Group Policy Object despite being surfaced through the Default Domain Policy GPO). Guerrilla then enumerates every msDS-PasswordSettings object under CN=Password Settings Container,CN=System,DC=<domain> and reads msDS-MinimumPasswordLength, msDS-PasswordSettingsPrecedence, and the msDS-PSOAppliesTo backlink to identify which users and groups each PSO targets. For every user object in scope the check resolves the effective policy by selecting the PSO with the lowest precedence value that applies to the user (directly or via group membership), falling back to the domain default when no PSO matches. Findings are raised when (a) the domain default minPwdLength is less than 14, (b) any PSO targeting a non-privileged population is less than 14, or (c) any PSO targeting a Tier 0 or Tier 1 group (Domain Admins, Enterprise Admins, Schema Admins, Account Operators, Backup Operators, Server Operators, Print Operators, krbtgt-adjacent service accounts) is less than 25.
Why it matters
Minimum password length is the single largest variable in offline cracking time. Active Directory stores user passwords as unsalted MD4 (NT hash) in NTDS.dit; once an attacker extracts the database via DCSync (T1003.006), volume shadow copy, or NTDS.dit theft from a backup, every hash is portable and crackable on attacker-controlled hardware with no rate limiting, no lockout, and no telemetry. A single RTX 4090 sustains roughly 288 GH/s against NTLM in hashcat -m 1000 (Chick3nman benchmarks, 2023), and an 8 x RTX 4090 rig exceeds 2.3 TH/s. At those rates the full keyspace for an 8-character password drawn from the 95-character printable ASCII set (6.6 x 10^15 candidates) exhausts in under eight hours; a 10-character password exhausts in roughly three months; a 12-character password takes approximately 230 years brute force but falls to weeks with a quality wordlist and rule set against the real-world distribution of human-chosen passwords. At 14 characters with no dictionary overlap, brute force becomes infeasible and dictionary attacks remain the only viable path, which a passphrase-style policy mitigates. For privileged accounts the calculus is more aggressive: a Domain Admin hash that is crackable in months is a forest-takeover primitive, so 25 characters is the contemporary minimum and a long machine-generated string or smart-card-only enforcement is preferred.
Attack path
Step 1: NTDS extraction. The attacker reaches a domain controller via lateral movement or obtains backup tapes / VM snapshots and runs ntdsutil "ac i ntds" "ifm" "create full c:\temp" q q, or executes secretsdump.py -just-dc DOMAIN/user@DC, or invokes Mimikatz lsadump::dcsync /domain:contoso.local /all /csv. The output is a list of <username>:<rid>:<lm-hash>:<nt-hash> records covering every account in the domain. Step 2: Offline cracking. The hashes are transferred to a GPU rig and fed to hashcat in NTLM mode (hashcat -m 1000 -a 0 -O hashes.txt rockyou.txt -r OneRuleToRuleThemAll.rule for dictionary plus rules, then -a 3 ?a?a?a?a?a?a?a?a for masked brute force). Cracked plaintexts are written to a pot file alongside the user names. Step 3: Privilege selection. The attacker correlates cracked accounts against group membership (BloodHound, or the previously captured NTDS itself) and selects accounts with administrative reach: Domain Admins, accounts with DCSync rights, accounts on Tier 0 servers, accounts with constrained delegation to high-value services. Step 4: Re-entry and persistence. Using the cracked plaintext (not a hash), the attacker authenticates as the user via RDP, SMB, WinRM, or the web SSO portal, which generates clean authentication telemetry indistinguishable from the legitimate user. Plaintext also enables passing through MFA bypass paths that require interactive password entry (legacy protocols, ADFS forms auth, on-prem Exchange basic auth). Step 5: Long-term hold. Because human-chosen passwords are reused and seldom rotated, the same cracked plaintext typically grants access to Azure AD / Entra ID via password hash sync, to VPN endpoints, and to third-party SaaS that federates against AD. The attacker pivots without re-cracking until a forced reset event invalidates the credential.
How Guerrilla assesses it
Guerrilla performs the check entirely over LDAP, no DC RPC required. It executes (objectClass=domainDNS) against the configured domain naming context and reads minPwdLength, maxPwdAge, minPwdAge, pwdHistoryLength, lockoutThreshold, lockoutDuration, and pwdProperties. It then issues (objectClass=msDS-PasswordSettings) under CN=Password Settings Container,CN=System,<defaultNamingContext> and reads msDS-MinimumPasswordLength, msDS-PasswordSettingsPrecedence, msDS-PSOAppliesTo, msDS-LockoutThreshold, and msDS-PasswordHistoryLength on each PSO. For PSO scope resolution the check uses a tokenGroups-style transitive membership walk: for every member of msDS-PSOAppliesTo it expands nested groups via (member:1.2.840.113556.1.4.1941:=<group DN>) so users inheriting a PSO through nested group membership are correctly attributed. Privileged group membership is resolved via the same matching-rule-in-chain filter against the well-known SIDs of the protected groups (S-1-5-21-<domain>-512, -519, -518, -548, -551, -549, -550). The output enumerates each policy scope (Default, PSO name), its minimum length, the count of users it covers, and a verdict tier (PASS at 14+ for standard, PASS at 25+ for privileged, FAIL otherwise).
Recommended value
Minimum 14 characters for standard users, 25 characters for privileged accounts
Remediation
Configure minimum password length in the Default Domain Policy or appropriate FGPP: Computer Configuration > Policies > Windows Settings > Security Settings > Account Policies > Password Policy > Minimum password length = 14. Create a stricter FGPP for privileged accounts requiring 25+ characters
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
- IA-5(1)
- CIS Benchmark
- 1.1.4
- ANSSI
- R34
- CIS AD Benchmark
- 5.2.1
- MITRE ATT&CK
- T1110.001, T1110.003