ADPWD-010: Users with Blank Passwords
- Platform
- Active Directory
- Category
- AD Password & Lockout Policies
- Severity
- Critical
- 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 issues an LDAP query against the domain partition for objects with objectCategory=person and objectClass=user where userAccountControl has bit 0x0020 (ADS_UF_PASSWD_NOTREQD = 32) asserted and bit 0x0002 (ADS_UF_ACCOUNTDISABLE) is clear. The LDAP filter used is: (&(objectCategory=person)(objectClass=user)(userAccountControl:1.2.840.113556.1.4.803:=32)(!(userAccountControl:1.2.840.113556.1.4.803:=2))) The matching rule 1.2.840.113556.1.4.803 is LDAP_MATCHING_RULE_BIT_AND, which evaluates the bitmask. For each hit the check returns sAMAccountName, distinguishedName, the decoded userAccountControl flags, pwdLastSet, lastLogonTimestamp, memberOf, and whether the account is a member of a protected group. The result is correlated against ADPWD-001 (domain password policy) and ADPRIV-001 (Tier-0 membership) so that a PASSWD_NOTREQD flag on a privileged or service account is escalated in the report. Disabled accounts are excluded from the finding because they cannot authenticate, but they are logged at Informational so cleanup can include them.
Why it matters
PASSWD_NOTREQD removes the account from password policy enforcement. The domain controller will accept an empty unicodePwd when the attribute is written, and the Kerberos AS_REQ / NTLM NEGOTIATE flow will accept an empty secret because the stored hash for an empty string is the well-known NT hash 31d6cfe0d16ae931b73c59d7e0c089c0. There is no lockout protection in many configurations because the authentication succeeds on the first attempt. The flag is most commonly introduced by: - Account creation scripts that call New-ADUser without -AccountPassword and without -PasswordNotRequired:$false, which silently sets the flag. - Legacy migration tools and Identity Management connectors that pre-stage accounts before the source system provides a password. - Helpdesk workflows that clear the password to "reset" a forgotten credential without setting a new one. - Computer objects pre-created with Add-ADComputer, where the flag is expected (machine account negotiates its own password on join), but the object is sometimes left abandoned. A single enabled user with this flag is enough for an attacker who can enumerate sAMAccountName values (which is unauthenticated on a Windows network through SMB null sessions, RID cycling, or LDAP anonymous bind on legacy forests) to authenticate as that user and pivot. If the account holds any group rights, the blast radius is whatever those rights confer; if it is in a protected group, the result is immediate Tier-0 compromise.
Attack path
1. Enumeration: the attacker collects domain user names with no credentials via SMB null session (enum4linux-ng, rpcclient lookupnames), Kerberos pre-auth username probing (kerbrute userenum), or an anonymous LDAP bind on misconfigured forests. 2. Discovery: with any valid low-privilege credential, BloodHound or PowerView surfaces PASSWD_NOTREQD accounts. Examples: Get-DomainUser -UACFilter PASSWD_NOTREQD Get-ADUser -Filter "userAccountControl -band 32 -and Enabled -eq 'True'" -Properties userAccountControl 3. Authentication: the attacker attempts authentication with an empty password. With Impacket: python3 -c "from impacket.smbconnection import SMBConnection; c=SMBConnection('dc01', '10.0.0.10'); c.login('svc-legacy', '')" Or with NetExec / CrackMapExec: nxc smb dc01 -u svc-legacy -p '' nxc ldap dc01 -u svc-legacy -p '' 4. Kerberos path: the attacker requests a TGT with an empty password using Rubeus or impacket-getTGT, then uses the resulting ticket for lateral movement, Kerberoasting, or DCSync if the account holds replication rights. 5. Privilege escalation: if the compromised account has any local admin rights on member systems (BloodHound AdminTo edge), the attacker pivots and dumps LSASS. If it has any AD object rights (BloodHound DACL edges), the attacker escalates through the ACL graph. 6. Persistence: the attacker frequently leaves the flag in place because it provides reliable, low-noise re-entry that survives password resets of other accounts.
How Guerrilla assesses it
Guerrilla uses System.DirectoryServices.Protocols to issue a single paged LDAP search with the bitmask filter above against the writable domain naming context. The check parses the integer userAccountControl into its named flags, computes the account age from whenCreated, and resolves group membership via tokenGroups (single round-trip, transitive) so that membership in Domain Admins, Enterprise Admins, Schema Admins, Account Operators, Backup Operators, Server Operators, Print Operators, and any custom Tier-0 group is flagged. The check runs against any reachable DC, requires only a member-of-Domain Users principal, and is non-intrusive. It does not attempt to authenticate with an empty password to confirm the bypass: the flag is sufficient to fail the check. Optional cross-checks correlate the finding with Security Event ID 4738 (user account changed) and 4720 (user account created) on the PDC to identify the source process or operator that introduced the flag.
Recommended value
No enabled accounts with blank passwords or PASSWD_NOTREQD flag
Remediation
Identify accounts using Get-ADUser -Filter {PasswordNotRequired -eq $true -and Enabled -eq $true}. Clear the PASSWD_NOTREQD flag and set a strong password on all identified accounts immediately. Review account creation scripts and processes to prevent this flag from being set in the future
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 |
| no-data | Not Assessed |
Framework mappings
- NIST SP 800-53
- IA-5(1), IA-2
- ANSSI
- R36
- CIS AD Benchmark
- 5.5.1
- MITRE ATT&CK
- T1078.002, T1078