ADPWD-014: Default/Common Passwords
- 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 operates on the NT hash side: Guerrilla supplies the wordlist (default = SecLists 10-million-password-list-top-1000.txt plus a generated domain-specific stem list using the domain NetBIOS name, company name, season + year combinations, and common keyboard walks), computes the MD4(UTF-16-LE(password)) NT hash for each candidate, and compares against the unicodePwd-derived hash material for every enabled user account. The hash material is obtained one of three ways depending on the run mode: - DSInternals Get-ADReplAccount (uses MS-DRSR Get-NCChanges, requires DS-Replication-Get-Changes + DS-Replication-Get-Changes-All, no NTDS dump to disk). - Offline NTDS.dit + SYSTEM hive parse via DSInternals Get-ADDBAccount (read-only against an evidence copy, no production exposure). - DSInternals Test-PasswordQuality against a pre-built hash table from either of the above. For each account the check emits: sAMAccountName, distinguishedName, userAccountControl flags (DISABLED, PASSWD_NOTREQD, DONT_EXPIRE_PASSWORD), adminCount, group memberships if privileged, the password-match category (top-1000, username-equals-password, company-stem, season-year, default-vendor), and pwdLastSet. Accounts where the password has not been changed since the last common-password detection are flagged as repeat findings, which usually indicates a stale account or an owner who is recycling the same weak password through history.
Why it matters
A common password on any single account collapses the cost of intrusion to one HTTP POST or one Kerberos AS-REQ. The attacker does not need a 0-day, a phishing infrastructure, or a malware payload: the credential is already valid. Three concrete blast radii compound. First, foothold: a single common password on a low-privilege user is sufficient to authenticate to the internal network (VPN, Citrix, Azure AD / Entra ID sign-in, OWA, RDP gateway), enumerate the domain with PowerView or BloodHound, and begin lateral movement. Second, privilege escalation by graph: BloodHound shortest-path analysis routinely turns a single common-password user into Domain Admin in fewer than five edges because the compromised principal almost always has indirect rights (group memberships, GPO link permissions, computer object delegations) that the defender did not realize were exploitable. Third, persistence and re-entry: cracked NT hashes from NTDS dumps that match common-password patterns are reused across cloud SaaS, VPN, and the same users personal accounts for follow-on phishing, which means a weak password keeps working long after the incident-response team has rotated the obvious credentials. Microsoft Defender for Identity, Mandiant M-Trends, the Verizon DBIR, and CISA advisories all consistently list weak or default credentials as a top-five initial-access vector. The 2024 Snowflake incident, the 2023 23andMe credential-stuffing breach, and the long tail of Citrix / VPN compromises every quarter all trace back to the same primitive: one user, one common password, one valid authentication.
Attack path
Step 1: Username enumeration. The attacker scrapes UserPrincipalName values from OWA, Autodiscover, Teams presence, or Azure AD / Entra ID, and supplements with sAMAccountName generation from the public company directory. A typical mid-size enterprise yields 2,000 to 20,000 candidate usernames. Step 2: Wordlist preparation. The attacker assembles a candidate password list from SecLists (10-million-password-list-top-100 or top-1000), seasonal patterns (Spring2026!, Summer2026!), the company name with common decorators (Contoso1!, Contoso2026), and the NetBIOS domain name. Many attackers use the same default Test-PasswordQuality wordlist that defenders ship with. Step 3: Low-and-slow spray. The attacker runs kerbrute passwordspray, MSOLSpray, or DomainPasswordSpray against Kerberos pre-auth, Azure AD / Entra ID sign-in, OWA, or LDAP simple bind. With one password per user per observation window the spray stays under the default lockoutThreshold even if account lockout is configured. First-pass hit rates of 1 to 5 percent are typical against environments that have never run a common-password audit. Step 4: Triage hits for value. The attacker pipes every valid credential through BloodHound to compute shortest-path-to-Domain-Admin. Service accounts with SPNs become Kerberoasting targets (ADKERB-001), accounts with PASSWD_NOTREQD or DONT_EXPIRE_PASSWORD become long-term beacons, and any hit on an account in Tier 0 ends the engagement. Step 5: NTDS extraction and offline confirmation. Once Domain Admin is reached, the attacker pulls NTDS.dit via DCSync (Impacket secretsdump.py, Mimikatz lsadump::dcsync) and runs hashcat -m 1000 against the same common-password wordlists. Every account whose NT hash matches the wordlist is enumerated and the cleartext is captured for cross-platform reuse. Step 6: Credential reuse. The attacker tries the cracked cleartexts against the corporate VPN, Microsoft 365, GitHub Enterprise, AWS IAM, the same users personal Gmail (for phishing pivot), and any SaaS that does not enforce SSO. The Have I Been Pwned dataset shows that approximately 60 to 70 percent of users reuse passwords across at least one boundary, which is why a single common-password hit in AD typically leaks into adjacent identity planes.
How Guerrilla assesses it
Guerrilla wraps DSInternals Test-PasswordQuality and feeds it a hash table extracted by Get-ADReplAccount (online, using MS-DRSR Get-NCChanges replication semantics) or Get-ADDBAccount (offline, against a forensic copy of NTDS.dit + SYSTEM hive). The candidate wordlist is the union of: SecLists Common-Credentials/10-million-password-list-top-1000.txt, a per-domain generated list (NetBIOS name, DNS short name, company name from msExchOrganizationName or the operator-provided -CompanyName parameter, current + previous year, season + year combinations, common keyboard walks Qwerty123!, Asdf1234!), and an optional operator-supplied custom wordlist. For each candidate the NT hash is computed as MD4(UTF-16-LE(password)) and compared against the unicodePwd-derived hash material for every enabled account where userAccountControl does not have ACCOUNTDISABLE set. The match is hash-equality, not online authentication, so the check generates zero Event 4625 (failed logon) noise and cannot trip account lockout. Findings are emitted with sAMAccountName, distinguishedName, the match category, pwdLastSet, adminCount, and a flag for membership in any privileged group resolved via tokenGroups expansion. The check additionally surfaces the DSInternals -WeakPassword and -DuplicatePasswordGroups buckets so the operator can see hash-collision clusters (multiple accounts sharing the same NT hash, a common pattern for break-glass and provisioning templates).
Recommended value
No accounts using passwords from the top 1000 most common password lists or matching default password patterns
Remediation
Test password hashes against common password lists (such as SecLists) using DSInternals Test-PasswordQuality. Force immediate password changes on all accounts with common passwords. Implement Azure AD Password Protection which includes a global banned password list updated by Microsoft
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)
- ANSSI
- R34
- CIS AD Benchmark
- 5.5.5
- MITRE ATT&CK
- T1110.001, T1110.003, T1078.002