Auditar las ACL de Active Directory antes que el atacante
Cómo encontrar ACL peligrosas en AD como GenericAll y los derechos de DCSync, limpiar marcas adminCount obsoletas y usar BloodHound con fines defensivos.
El hardening de la directiva de grupo y los parches se llevan casi toda la atención, pero una parte enorme de los compromisos reales de Active Directory no tocan ningún CVE: abusan de permisos concedidos, heredados u olvidados. Una cuenta de servicio con permisos excesivos, una delegación obsoleta de una herramienta de soporte ya retirada o una entidad de servicio capaz de hacer DCSync pueden entregar a un atacante el dominio completo sin un solo exploit. Esta guía explica cómo encontrar y corregir esas rutas antes de que lo haga otro.
Las ACL que más importan
Los objetos de Active Directory tienen listas de control de acceso discrecional (DACL) igual que los archivos, pero los derechos relevantes para la seguridad forman un conjunto pequeño y bien conocido:
| Derecho | Qué permite | Por qué es peligroso |
|---|---|---|
GenericAll | Control total del objeto | Puede restablecer contraseñas, modificar la pertenencia a grupos y editar cualquier atributo |
GenericWrite | Escribir cualquier atributo no protegido | Puede establecer scriptPath para ejecutar un script de inicio de sesión o alterar atributos de pertenencia a grupos |
WriteDACL | Modificar la propia ACL del objeto | El beneficiario puede concederse GenericAll a voluntad y eludir cualquier revisión futura |
WriteOwner | Tomar posesión del objeto | El nuevo propietario obtiene implícitamente la capacidad de concederse cualquier derecho |
DS-Replication-Get-Changes + DS-Replication-Get-Changes-All | Solicitar datos de replicación del directorio | Juntos permiten DCSync: obtener los hashes de contraseña de cualquier cuenta, incluida krbtgt, sin tocar el disco de un DC |
Cualquiera de los cuatro primeros derechos sobre un grupo como Domain Admins, o sobre el propio objeto AdminSDHolder, equivale al compromiso total del dominio. Los derechos de replicación son peligrosos precisamente porque rara vez se auditan: la mayoría de los administradores solo piensan en revisar la pertenencia a grupos, no los permisos de replicación sobre el objeto de dominio.
Auditar las ACL con PowerShell
Empiece por el propio objeto raíz del dominio, ya que ahí residen los derechos de DCSync:
$domainDN = (Get-ADDomain).DistinguishedName
$acl = Get-Acl -Path "AD:\$domainDN"
$acl.Access | Where-Object {
$_.ActiveDirectoryRights -match "ExtendedRight" -and
($_.ObjectType -eq "1131f6aa-9c07-11d1-f79f-00c04fc2dcd2" -or # DS-Replication-Get-Changes
$_.ObjectType -eq "1131f6ad-9c07-11d1-f79f-00c04fc2dcd2") # DS-Replication-Get-Changes-All
} | Select-Object IdentityReference, ActiveDirectoryRights, ObjectTypeEstos dos GUID no son la única vía hacia DCSync: GenericAll, AllExtendedRights (una ACE de derecho extendido con ObjectType vacío) y WriteDACL sobre la raíz del dominio conceden los mismos derechos o permiten a su titular concedérselos. La auditoría de derechos de DCSync recoge la consulta completa y los titulares predeterminados esperados.
Después, rastree los derechos peligrosos en las OU de alto valor (Domain Controllers, OU de administración de Tier 0, grupos privilegiados):
$targets = @("OU=Domain Controllers,DC=corp,DC=example,DC=com",
"CN=Domain Admins,CN=Users,DC=corp,DC=example,DC=com")
foreach ($dn in $targets) {
Write-Host "== $dn ==" -ForegroundColor Cyan
(Get-Acl -Path "AD:\$dn").Access |
Where-Object { $_.ActiveDirectoryRights -match "GenericAll|GenericWrite|WriteDacl|WriteOwner" } |
Select-Object IdentityReference, ActiveDirectoryRights, AccessControlType
}Contraste cada IdentityReference devuelto con una lista de referencia de entidades integradas (SYSTEM, Enterprise Admins, Domain Admins, Administrators). Cualquier otra necesita un motivo de negocio documentado.
AdminSDHolder, SDProp y adminCount
Active Directory protege un conjunto fijo de grupos privilegiados (Domain Admins, Enterprise Admins, Schema Admins, Administrators, Account Operators, Backup Operators y algunos más) mediante un mecanismo llamado SDProp (SD Propagation). Cada 60 minutos, el proceso:
- Lee la ACL del objeto especial
AdminSDHolder. - Aplica esa ACL a todos los miembros actuales de un grupo protegido y sobrescribe cualquier personalización de ACL hecha directamente en esas cuentas.
- Establece
adminCount=1en cada miembro protegido y no lo borra automáticamente cuando la cuenta sale del grupo protegido.
Por eso los cambios de permisos que hace directamente en el objeto de usuario de un Domain Admin se revierten: SDProp los machaca en su siguiente ciclo. Y por eso adminCount=1 se convierte en una marca duradera, aunque imperfecta, de que «esta cuenta fue privilegiada en algún momento».
Para cambiar los permisos efectivos de las cuentas protegidas, edite la ACL del propio AdminSDHolder (con cuidado, porque se propaga a todas), no la de cada cuenta.
$adminSDHolderDN = "CN=AdminSDHolder,CN=System," + (Get-ADDomain).DistinguishedName
(Get-Acl -Path "AD:\$adminSDHolderDN").Access |
Where-Object { $_.ActiveDirectoryRights -match "GenericAll|WriteDacl|WriteOwner" } |
Select-Object IdentityReference, ActiveDirectoryRightsEncontrar y limpiar objetos obsoletos con adminCount=1
Las cuentas retiradas de grupos privilegiados conservan adminCount=1 y, lo que es crucial, mantienen la herencia deshabilitada en su ACL. Es decir, ya no reciben los cambios de permisos hechos en la OU, y su última ACL privilegiada conocida permanece indefinidamente. Es una ruta de «administrador en la sombra» muy habitual: una cuenta que parece corriente por su pertenencia a grupos, pero que todavía conserva entradas residuales de ACL privilegiada.
# Buscar usuarios con adminCount=1 que NO son miembros actuales de grupos protegidos
$protectedMembers = @()
foreach ($g in "Domain Admins","Enterprise Admins","Schema Admins","Administrators","Account Operators","Backup Operators") {
$protectedMembers += (Get-ADGroupMember -Identity $g -Recursive -ErrorAction SilentlyContinue).SamAccountName
}
Get-ADUser -Filter "adminCount -eq 1" -Properties adminCount, whenChanged |
Where-Object { $_.SamAccountName -notin $protectedMembers } |
Select-Object SamAccountName, DistinguishedName, whenChangedPara cada resultado obsoleto: confirme que la cuenta realmente ya no necesita derechos elevados y, después, vuelva a habilitar la herencia de la ACL para que herede de nuevo de su OU:
$obj = Get-ADUser -Identity "svc_legacybackup"
$acl = Get-Acl -Path "AD:\$($obj.DistinguishedName)"
$acl.SetAccessRuleProtection($false, $true) # desproteger, heredar del padre
Set-Acl -Path "AD:\$($obj.DistinguishedName)" -AclObject $acl
Set-ADUser -Identity "svc_legacybackup" -Clear adminCountHágalo por lotes y con revisión de cambios: borrar adminCount en una cuenta que sigue siendo legítimamente privilegiada (por ejemplo, mediante una pertenencia anidada que SDProp no detectó limpiamente) le quitará protecciones que todavía necesita.
Usar BloodHound y PingCastle con fines defensivos
La revisión manual de ACL escala mal a partir de unos pocos miles de objetos. Las herramientas de evaluación creadas para atacantes funcionan igual de bien apuntadas hacia dentro:
- BloodHound ingiere las ACL de AD, la pertenencia a grupos, los datos de sesión y los vínculos de GPO, y representa en un grafo las rutas de ataque («ruta más corta hacia Domain Admins»). Ejecútelo en modo de solo lectura, con una cuenta de recopilación dedicada sin derechos de escritura, y trate el resultado como un artefacto de auditoría interna, no como algo que se deja por ahí: el propio grafo es un mapa de objetivos.
- PingCastle genera un informe de estado puntuado que cubre objetos obsoletos, errores de configuración de ACL, riesgos de confianzas y anomalías de AdminSDHolder, con una puntuación de tendencia que puede seguir de una versión a otra.
Ejecútelos de forma periódica (mensualmente es razonable en la mayoría de los entornos), conserve el histórico de informes y haga seguimiento del número de hallazgos «críticos» como métrica, no como un ejercicio de limpieza puntual.
Verificación
Tras corregir un hallazgo, vuelva a ejecutar exactamente la consulta que lo detectó y confirme que el resultado está limpio:
# Volver a comprobar los derechos equivalentes a DCSync (GUID de replicación, AllExtendedRights, GenericAll, WriteDACL) tras la corrección
$domain = Get-ADDomain
$rootSid = (Get-ADDomain (Get-ADForest).RootDomain).DomainSID.Value
$expected = @(
'S-1-5-18', # SYSTEM
'S-1-5-9', # Enterprise Domain Controllers
'S-1-5-32-544', # Administrators (built-in)
"$($domain.DomainSID.Value)-516", # Domain Controllers
"$($domain.DomainSID.Value)-512", # Domain Admins (default WriteDACL)
"$rootSid-519", # Enterprise Admins (default GenericAll)
"$rootSid-498" # Enterprise Read-only Domain Controllers (Get-Changes only)
)
$repl = @([guid]'1131f6aa-9c07-11d1-f79f-00c04fc2dcd2', [guid]'1131f6ad-9c07-11d1-f79f-00c04fc2dcd2')
$acl = Get-Acl -Path "AD:\$($domain.DistinguishedName)"
$acl.GetAccessRules($true, $true, [System.Security.Principal.SecurityIdentifier]) | Where-Object {
$r = $_.ActiveDirectoryRights
$_.AccessControlType -eq 'Allow' -and
-not $_.PropagationFlags.HasFlag([System.Security.AccessControl.PropagationFlags]::InheritOnly) -and
$_.IdentityReference.Value -notin $expected -and (
$r.HasFlag([System.DirectoryServices.ActiveDirectoryRights]::GenericAll) -or
$r.HasFlag([System.DirectoryServices.ActiveDirectoryRights]::WriteDacl) -or
($r.HasFlag([System.DirectoryServices.ActiveDirectoryRights]::ExtendedRight) -and
($_.ObjectType -in $repl -or $_.ObjectType -eq [guid]::Empty))
)
}
# No debería haber salida, salvo excepciones documentadas como la cuenta del conector AD DS de Entra ConnectQué se rompe
- La administración delegada legítima. Los grupos de soporte técnico limitados a restablecer contraseñas en una OU concreta, los equipos de aplicaciones que gestionan sus propias cuentas de servicio y el software de copia de seguridad que necesita derechos cercanos a la replicación pueden aparecer como «hallazgos». Eliminarlos sin revisión rompe flujos de trabajo reales: valídelo con un responsable del cambio antes de revocar nada.
- Herramientas de terceros integradas con AD (copia de seguridad, gobierno de identidades, soluciones PAM) que a veces requieren derechos amplios por diseño; consulte la documentación del fabricante antes de quitar permisos a su cuenta de servicio.
- Automatizaciones que dependen de que adminCount se borre: si un script o una herramienta de aprovisionamiento espera que
adminCountrefleje en tiempo real la pertenencia actual a grupos, tendrá que tener en cuenta el ciclo de una hora de SDProp y que el borrado no es automático.
Combine esta auditoría con los límites de identidad descritos en Tier 0 y acceso privilegiado, y repítala cada vez que retire una herramienta de administración delegada o un flujo de trabajo del soporte técnico: son el origen más habitual de concesiones de ACL huérfanas.
Preguntas frecuentes
¿Cuál es la forma más rápida de saber quién puede hacer DCSync en mi dominio?
Ejecute Get-Acl sobre el objeto del contexto de nomenclatura del dominio y filtre las entidades de seguridad que tengan a la vez DS-Replication-Get-Changes y DS-Replication-Get-Changes-All, o bien GenericAll, AllExtendedRights o WriteDACL, que los incluyen o permiten concederlos. De forma predeterminada, los controladores de dominio tienen ambos derechos a través de los grupos Domain Controllers y Enterprise Domain Controllers, el grupo Administrators integrado tiene ambos (lo que abarca a Domain Admins y Enterprise Admins) y Enterprise Read-only Domain Controllers solo tiene Get-Changes. Cualquier otra entidad que tenga los dos derechos, o uno de los derechos más amplios, puede ejecutar DCSync.
¿Por qué vuelven a aparecer los permisos que elimino de la cuenta de un Domain Admin?
Se debe a AdminSDHolder y al proceso SDProp. Cada 60 minutos, SDProp restablece la ACL de todos los miembros de un grupo protegido (Domain Admins, Enterprise Admins, etc.) para que coincida con la ACL del objeto AdminSDHolder, y sobrescribe cualquier permiso personalizado que haya añadido directamente en ese usuario.
¿Es seguro quitar sin más GenericAll y WriteDACL de todas las cuentas que no son de administración?
No sin revisarlo antes. Algunas de esas concesiones son administración delegada legítima, como un grupo de administración de OU del soporte técnico que necesita GenericAll limitado a una OU concreta. Audite cada hallazgo, asócielo a una finalidad de negocio prevista y elimine solo lo que no tenga justificación.
Auditar las ACL de Active Directory antes que el atacante