ADPWD-015: Distribución de la antigüedad del último establecimiento de contraseña
- Plataforma
- Active Directory
- Categoría
- AD Password & Lockout Policies
- Severidad
- Medium
- Pilar de Zero Trust
- Identity (peso 3)
- Fixtures de referencia
- 3
- Cobertura de ramas
- Observada: los fixtures prueban los veredictos que ejercitan
- Procedencia
- baseline
Qué comprueba
Analizar la distribución de la antigüedad de las contraseñas en todas las cuentas revela la eficacia de la aplicación de la política e identifica cuentas con contraseñas extremadamente antiguas. Las cuentas con contraseñas sin cambiar durante años pueden haber quedado excluidas de los cambios de política o tener establecido el indicador de contraseña que nunca expira
Por qué importa
Old passwords are a force multiplier for every credential-attack technique in the ATT&CK matrix. NTLM hashes do not change with time on disk: an NTDS.dit extract from three years ago still works today if the password has not been rotated, which is why dumps from prior incidents continue to surface in fresh intrusions as long as the underlying hashes remain valid. Kerberoasting yields RC4 or AES-256 hashes that are cracked offline at GPU speed, and a 14-character password set in 2018 has been exposed to credential-stuffing wordlists, prior breach corpora, and adversary-controlled rainbow tables for the entire window since it was set. Accounts with DONT_EXPIRE_PASSWD set bypass every Group Policy and PSO control, and in field engagements they are concentrated in three populations: legacy service accounts created when password rotation was operationally painful, break-glass accounts whose owners feared lockout, and individual user accounts where a help-desk technician flipped the bit to suppress a ticket. The blast radius of a single old privileged password is the entire forest. NIST SP 800-63B no longer recommends arbitrary periodic rotation for human users, but it explicitly requires rotation on indicators of compromise and applies different guidance to shared, service, and privileged identities, which is precisely the population this check surfaces. CIS Microsoft Active Directory Benchmark 5.6.x and PCI DSS 8.3 still require demonstrable rotation for service and privileged accounts.
Ruta de ataque
Step 1: Reconnaissance. The attacker, holding any authenticated foothold, runs an LDAP query for (&(objectCategory=person)(objectClass=user)(!(userAccountControl:1.2.840.113556.1.4.803:=2))) and pulls pwdLastSet and userAccountControl. PowerView Get-DomainUser -PreauthNotRequired -Properties samaccountname,pwdlastset,useraccountcontrol or a raw ldapsearch works equally well. No privileges beyond Authenticated Users are required. Step 2: Triage. The attacker filters for accounts where (pwdLastSet age > 365 days) OR (userAccountControl AND 0x10000 != 0), then intersects with adminCount=1 and with accounts holding a servicePrincipalName. The output is a small, prioritized target list of stale privileged identities and stale kerberoastable service accounts. Step 3: Offline cracking against kerberoastable targets. For each SPN-bearing target the attacker requests a service ticket: Rubeus kerberoast /user:svc_target /nowrap or GetUserSPNs.py -request. The ticket carries an RC4-HMAC TGS encrypted with the target service account NTLM hash (or AES-256 if the account is configured for AES). The attacker runs hashcat -m 13100 against a wordlist enriched with breach corpora from the years the password was first set. A 10-character password from 2017 typically falls in hours; a password reused from any prior breach falls instantly. Step 4: Password spraying against human accounts. For non-SPN targets with DONT_EXPIRE_PASSWD set, the attacker sprays one or two candidate passwords per account per lockout window (T1110.003). Stale passwords are disproportionately likely to be seasonal patterns, vendor defaults, or values from public breach corpora because the policy at the time of set was weaker. Step 5: Reuse. The cracked credential is used directly (RDP, WinRM, SMB) or to forge a TGT via S4U2Self for protocol transition. Service accounts often have local admin rights on the servers they run on, so a single cracked stale service account commonly yields lateral movement to dozens of hosts without ever touching a domain controller. Step 6: Persistence. The attacker leaves the password unchanged. As long as DONT_EXPIRE_PASSWD remains set or rotation is not enforced, the credential remains valid indefinitely and survives password resets on other accounts, IR cycles, and credential audits that do not specifically scope this population.
Cómo lo evalúa Guerrilla
Guerrilla binds to the default naming context using the current security principal and issues a paged LDAP search with filter (&(objectCategory=person)(objectClass=user)(!(userAccountControl:1.2.840.113556.1.4.803:=2))) and attribute list pwdLastSet, userAccountControl, sAMAccountName, distinguishedName, lastLogonTimestamp, adminCount, servicePrincipalName, memberOf. The pwdLastSet FileTime is converted via [DateTime]::FromFileTime() and the elapsed days are computed against Get-Date. The DONT_EXPIRE_PASSWD bit is tested with (userAccountControl -band 0x10000). The effective maximum password age is computed by reading maxPwdAge on the domain object (a negative FileTime, converted to a positive day count) and overlaying every msDS-PasswordSettings PSO via the resultant-set algorithm: per-user assignment wins over per-group assignment, and within each tier the PSO with the lowest msDS-PasswordSettingsPrecedence wins. Accounts whose effective age exceeds the effective max age are flagged. The output is structured as histogram buckets (0-30, 31-60, 61-90, 91-180, 181-365, 366-730, 731-1825, 1826+ days) plus a flat list of outliers, with privileged accounts and SPN-bearing accounts tagged. No writes are performed.
Valor recomendado
Ninguna cuenta de usuario habilitada con contraseñas más antiguas que la política de antigüedad máxima de contraseña. La distribución debe mostrar patrones de rotación regular
Remediación
Genere un informe de distribución de la antigüedad de contraseñas con Get-ADUser -Filter {Enabled -eq $true} -Properties PasswordLastSet | Group-Object {(New-TimeSpan $_.PasswordLastSet (Get-Date)).Days -replace '\d$','0'}. Investigue las cuentas con contraseñas más antiguas de lo que permite la política. Fuerce cambios de contraseña donde sea necesario y revise los indicadores de contraseña que nunca expira
Veredictos probados con fixtures
Cada veredicto de esta tabla está probado por un fixture de referencia en la suite de pruebas que valida el módulo. La tabla se deriva de la última ejecución en verde; no puede editarse a mano.
| Escenario | Veredicto esperado |
|---|---|
| clean | PASS |
| known-bad | WARN |
| throttled | Not Assessed |
Mapeos a marcos de referencia
- NIST SP 800-53
- IA-5(1)
- CIS AD Benchmark
- 5.6.1
- MITRE ATT&CK
- T1078.002