ADPWD-019: Azure AD Password Protection
- Platform
- Active Directory
- Category
- AD Password & Lockout Policies
- Severity
- Medium
- Zero Trust pillar
- Identity (weight 3)
- Golden fixtures
- 1
- Branch coverage
- Observed: fixtures prove the verdicts they exercise
- Provenance
- baseline
What it checks
The check evaluates four conditions across AD, the registry of every domain controller, and the Azure AD Password Protection service registration in the forest: 1. Proxy service registration. Guerrilla enumerates the service connection point objects under CN=Azure AD Password Protection,CN=Services,CN=Configuration,DC=forest,DC=tld and lists every registered Proxy. At least two proxies are required for resiliency. Each Proxy must have a heartbeat newer than 24 hours. 2. DC Agent presence. For every DC returned by Get-ADDomainController -Filter *, the check reads HKLM:\SOFTWARE\Microsoft\Azure AD Password Protection\DC Agent and the running state of the AzureADPasswordProtectionDCAgent service. A DC without the agent silently accepts any password the legacy SAM/Kerberos engine allows. 3. Policy mode. The check binds to the Azure AD tenant via Get-AzureADPasswordProtectionDCAgent or the equivalent Graph endpoint and reads the EnableBannedPasswordCheckOnPremises and PasswordProtectionEnforceMode flags. Mode = Audit logs rejections but does not block them; mode = Enforce is the required state. 4. Custom banned list. The check pulls the CustomBannedPasswordList from the tenant Authentication Methods policy and counts the entries. An empty list (or one with only the placeholder example values) is flagged. The global Microsoft list is always on and does not need to be configured. The check also reads recent Event IDs from the Microsoft-AzureADPasswordProtection-DCAgent/Admin and /Operational channels (10014 password rejected, 10015 password accepted, 30007 mode change) to confirm the agent is actually evaluating passwords rather than idle.
Why it matters
Native Active Directory password policy enforces length, complexity, history, and age. None of those controls prevent a user from choosing Password1, Welcome2026, Contoso!, or Spring2026. Microsoft research on hundreds of millions of compromised credentials shows that more than 80 percent of password-based breaches involve a password from a short, well-known list of common patterns. Azure AD Password Protection is the only Microsoft-supported on-premises control that blocks those patterns at the moment of password change. Without it, an organization that has invested in MFA, Conditional Access, and Identity Protection in the cloud still has a domain where a tier-zero service account can be set to Welcome1. The blast radius is largest in three scenarios. First, password spray: an external attacker who can reach LDAP, SMB, OWA, or ADFS rotates a single weak password across every enumerable account. Spray runs that fail against an Entra tenant (because cloud banned-password is always on) succeed against synced on-prem accounts whose hybrid password landed before Password Protection was deployed, or against on-prem-only accounts that never touched the cloud. Second, helpdesk-reset abuse: helpdesk operators frequently set temporary passwords like Welcome1 or the user first name plus a digit; without DC Agent enforcement these survive into production. Third, post-incident credential rotation: after a DCSync or NTDS.dit extraction, the IR team forces a domain-wide reset; if Password Protection is in Audit mode, users restore the same weak patterns and the attacker spray list still works. The control is also a prerequisite for any meaningful detection rule around password spray. Rules built on Event ID 4625 (failed logon) and 4771 (Kerberos pre-auth failure) generate a usable signal only when the password floor has eliminated the trivially-guessable patterns. With Password Protection in Enforce mode and a populated custom list, spray attempts collapse to a tight statistical signature that SIEM correlation can flag with high confidence.
Attack path
1. Reconnaissance. The attacker confirms the absence of Password Protection by attempting to set a known-banned password on an account they control (an existing low-privilege user, a fresh user created via a stolen Account Operator session, or a self-service password reset). If Welcome1 or the company name plus a digit is accepted, the DC Agent is absent or in Audit. 2. User enumeration. The attacker enumerates SAM account names via LDAP (any authenticated user), Kerberos pre-auth enumeration (Rubeus, kerbrute), or a public list of email addresses harvested from LinkedIn and breached corpora. 3. Spray. The attacker runs a slow, paced password spray (one or two attempts per account per lockout window) using kerbrute, DomainPasswordSpray, MSOLSpray, or a custom Kerberos pre-auth loop. The candidate list is short and seasonal: Spring2026, Summer2026!, Welcome1, the company name, the city, the sports team, and the product line. With Password Protection absent, the success rate on a 5,000-user domain is typically 1 to 3 percent within a single spray run. 4. Foothold. The first valid credential set is used for SMB, RDP, or OWA logon depending on the service exposure. From a non-privileged foothold the attacker pivots to LSASS dumping, Kerberoasting (T1558.003), and AS-REP roasting (T1558.004), where additional weak passwords (Service2026!, BackupAdmin1) collapse offline within minutes against hashcat with a targeted ruleset. 5. Persistence. The attacker creates or resets a Tier-0 service account password to a known-weak value (still accepted because the DC Agent is missing) and documents the credential in a private store. After IR resets the password during cleanup, the attacker re-sprays the same patterns and recovers access. Without Password Protection, the rotation does not raise the floor. 6. Evasion. Because rejected password changes generate no event when the DC Agent is absent, none of the above is visible in the standard 4625/4740 channels. The defender sees only successful logons from valid credentials.
How Guerrilla assesses it
Guerrilla uses four signals to produce a single verdict per domain. First, it enumerates the proxy service connection point under CN=Azure AD Password Protection,CN=Services,CN=Configuration,DC=forest,DC=tld via Get-ADObject and counts active proxies. Fewer than two, or any proxy whose lastHeartbeat attribute is older than 24 hours, is reported. Second, it iterates every DC from Get-ADDomainController -Filter * and, via Invoke-Command, reads the AzureADPasswordProtectionDCAgent service state and the registry values under HKLM:\SOFTWARE\Microsoft\Azure AD Password Protection\DC Agent (HeartbeatTimestamp, PolicyDate, AzureTenant). DCs without the agent installed, or with a heartbeat older than 24 hours, are listed individually so the operator knows which DCs to remediate. Third, when run with a Graph or AzureAD token, the check reads the tenant Authentication Methods policy via the Microsoft Graph endpoint /policies/authenticationMethodsPolicy and the legacy /beta/settings/Password Rule Settings to retrieve EnabledForOnPremises, Mode (Audit / Enforce), and the CustomBannedPasswordList. Mode = Audit and an empty custom list are both flagged. Fourth, it samples Event ID 10014 (password rejected) and 10015 (password accepted) from the Microsoft-AzureADPasswordProtection-DCAgent/Admin channel over the prior 30 days. Zero events on a production DC indicates the agent is installed but not receiving policy or not processing changes, which is functionally equivalent to absence. The check does not attempt a synthetic password change to verify enforcement; that would write to the directory and trip account-anomaly detectors. Operators who want active verification should set a test password on a disposable account and observe Event 10014 manually.
Recommended value
Azure AD Password Protection deployed in enforced mode with custom banned password list configured
Remediation
Deploy the Azure AD Password Protection proxy service and DC agent on all domain controllers. Configure a custom banned password list in Azure AD including organization-specific terms. Set the mode to Enforced (not Audit). Monitor password change rejections through event logs and Azure AD reporting
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 |
|---|---|
| not-implemented | Not Assessed |
Framework mappings
- NIST SP 800-53
- IA-5(1)
- CIS AD Benchmark
- 5.5.6
- MITRE ATT&CK
- T1110.001, T1110.003