Kerberos - Fundamentos: Protocolo, Autenticación y Ataques
Links: Kerberos Docs - Microsoft | KDC | Kerberos Delegation - Netwrix | You Do Not Understand Kerberos - ATTL4S
¿Qué es Kerberos?
Protocolo de autenticación centralizado basado en tickets. Usa el puerto 88 por defecto y es el protocolo de autenticación predeterminado en dominios Windows desde Windows 2000. Permite que los usuarios accedan a servicios de red sin enviar su contraseña por la red.
- Es stateless — el KDC no guarda historial de transacciones
- Usa criptografía simétrica con soporte opcional asimétrico (PKINIT)
- Las claves secretas son derivadas de las contraseñas de las cuentas
Entidades de Kerberos
- KDC (Key Distribution Center) — Servidor de autenticación central. En AD es el Domain Controller. Conoce las claves de todas las cuentas.
- Usuario (cliente) — Quien solicita acceso a un servicio
- Servicio — El recurso al que el usuario quiere acceder
Tickets
- TGT (Ticket Granting Ticket) — "Carnet de identidad" del usuario. Obtenido al autenticarse contra el KDC. Contiene info del usuario y tiene validez limitada (por defecto 10 horas). Cifrado con la clave del KDC.
- TGS ticket / ST (Service Ticket) — Ticket temporal para acceder a un servicio específico. Cifrado con la clave del servicio. El servicio lo descifra y lee los derechos del usuario.
Proceso de Autenticación
Fase 1 - Authentication Service (AS)
AS-REQ — El cliente solicita un TGT al KDC enviando su nombre de usuario en claro y un authenticator (timestamp cifrado con su propia clave) para demostrar su identidad.
AS-REP — El KDC verifica el authenticator, y si es válido responde con:
- El TGT cifrado con la clave del KDC (el usuario no puede modificarlo)
- Una session key cifrada con la clave del usuario
Si la pre-autenticación está deshabilitada, el KDC responde con el AS-REP sin verificar la identidad. Esto es lo que permite ASREPRoasting.
Fase 2 - Ticket-Granting Service (TGS)
TGS-REQ — El cliente envía al KDC:
- El nombre del servicio (SPN)
- Su TGT
- Un authenticator cifrado con la session key obtenida en AS-REP
TGS-REP — El KDC verifica el TGT y la session key, y responde con:
- El TGS ticket cifrado con la clave del servicio (contiene info del usuario y una nueva session key)
- La nueva session key cifrada con la session key del usuario/KDC
Fase 3 - Application Request (AP)
AP-REQ — El cliente envía al servicio:
- El TGS ticket (cifrado con la clave del servicio)
- Un authenticator cifrado con la session key usuario/servicio
AP-REP — El servicio descifra el TGS ticket con su propia clave, extrae la session key, verifica el authenticator, lee la info del usuario y decide si concede o deniega acceso.
Protección de los tickets
- El TGT está cifrado con la clave del KDC (krbtgt) → el usuario no puede leerlo ni modificarlo
- El TGS ticket está cifrado con la clave del servicio → el usuario no puede modificar sus propios permisos
- Cada fase genera una session key temporal para proteger los intercambios siguientes
Ataques contra Kerberos
ASREPRoasting
Si una cuenta tiene la pre-autenticación deshabilitada, cualquiera puede pedir un AS-REP en su nombre sin conocer su contraseña. La parte cifrada con la clave del usuario se puede crackear offline.
Por qué funciona
La primera fase de Kerberos (AS-REQ / AS-REP) normalmente exige que el cliente demuestre su identidad enviando un authenticator: un timestamp cifrado con la clave derivada de su propia contraseña. El KDC descifra ese authenticator con la clave que tiene almacenada para esa cuenta; si el resultado es un timestamp válido y reciente, confirma que el cliente conoce la contraseña correcta.
El problema aparece cuando una cuenta tiene el flag DONT_REQ_PREAUTH activo en su userAccountControl. Con este flag, el KDC se salta la verificación del authenticator por completo. No importa si el atacante conoce la contraseña o no — el KDC responde igual con un AS-REP.
La clave técnica es que una parte del AS-REP está cifrada con la clave derivada de la contraseña del usuario objetivo (específicamente, el enc-part del TGT contiene la session key, cifrada con esa clave). El atacante no necesita autenticarse para recibir esta respuesta; solo necesita conocer el nombre de usuario. Una vez tiene el AS-REP, puede intentar descifrar esa porción offline probando contraseñas candidatas: si al descifrar obtiene una estructura ASN.1 válida, la contraseña probada era correcta.
Ejemplo del flujo
- El atacante envía un
AS-REQparajenna.smithsin incluir ningún authenticator. - El KDC revisa el UAC de
jenna.smith, veDONT_REQ_PREAUTH, y responde con unAS-REPde todos modos. - El AS-REP contiene
$krb5asrep$23$jenna.smith@DOMAIN.LOCAL:<hash cifrado>. - El atacante ejecuta
hashcat -m 18200contra ese hash con una wordlist. Sijenna.smithusabaSummer2024!, Hashcat lo descubre porque al cifrar ese texto con la clave derivada de esa contraseña, el resultado coincide byte a byte con el hash capturado.
Por qué es detectable/raro
Requiere que un administrador haya deshabilitado explícitamente la pre-autenticación en la cuenta — no es el comportamiento por defecto de Active Directory. Suele encontrarse en cuentas de servicio configuradas por software legacy que no soporta bien Kerberos moderno.
Kerberoasting
Cualquier usuario autenticado puede pedir un TGS ticket para cualquier SPN del dominio. El TGS ticket está cifrado con la clave de la cuenta de servicio. Si esa cuenta tiene contraseña débil, se puede crackear offline.
Por qué funciona
En la segunda fase de Kerberos (TGS-REQ / TGS-REP), cualquier usuario ya autenticado (con un TGT válido, sin importar su nivel de privilegio) puede solicitar un Service Ticket para cualquier SPN existente en el dominio. El KDC no valida si el usuario "debería" tener acceso a ese servicio en este punto — esa decisión la toma el propio servicio al recibir el ticket, no el KDC al emitirlo.
El TGS ticket que el KDC entrega está cifrado con la clave secreta de la cuenta que expone el SPN (la cuenta de servicio). El atacante recibe este ticket cifrado sin poder leer su contenido, pero eso no le importa: lo que quiere es el ticket cifrado en sí, porque puede intentar descifrarlo offline probando contraseñas candidatas contra ese blob cifrado, igual que con ASREPRoasting pero en la fase TGS en vez de AS.
La vulnerabilidad de fondo es que SPNs suelen estar asociados a cuentas de usuario normales (en vez de cuentas de máquina, que tienen contraseñas de 120 caracteres aleatorios imposibles de crackear). Un admin que configura un servicio SQL usando una cuenta de dominio con contraseña "humana" está exponiendo esa contraseña a cualquier usuario autenticado del dominio, sin que se dé cuenta.
Ejemplo del flujo
- El atacante, autenticado como cualquier usuario de dominio, enumera cuentas con SPN: encuentra
sqldevcon el SPNMSSQL_svc_dev/sql01.domain.local:1443. - Envía un
TGS-REQpidiendo un ticket para ese SPN. El KDC lo emite sin objeción — es una operación completamente normal y esperada de Kerberos. - El TGS ticket recibido está cifrado con la clave de
sqldev. El atacante extrae ese blob:$krb5tgs$23$*sqldev$DOMAIN.LOCAL$MSSQL_svc_dev...*$<hash>. - Ejecuta
hashcat -m 13100y descubre que la contraseña desqldevesWelcome1. - Ahora tiene credenciales válidas de dominio para
sqldev, que puede usar para autenticarse directamente contra el servidor SQL o continuar moviéndose lateralmente.
Por qué RC4 lo hace más fácil
Si la cuenta soporta cifrado RC4 ($23$), el hash es más rápido de crackear que si usa AES ($18$), porque RC4 no tiene el mismo costo computacional de derivación de clave que AES con múltiples iteraciones. Por eso Rubeus tiene la opción /tgtdeleg para forzar que el KDC devuelva RC4 en dominios donde ambos cifrados están soportados como fallback.
Delegation Attacks
Kerberos permite que un servicio suplante a un usuario para acceder a otros recursos. Hay tres tipos con distintas vulnerabilidades:
- Unconstrained Delegation — el servicio puede impersonar al usuario ante cualquier servicio
- Constrained Delegation — limitado a servicios específicos
- Resource-Based Constrained Delegation (RBCD) — el recurso destino controla quién puede delegar
Unconstrained Delegation — ejemplo técnico
Si SQL01$ tiene TRUSTED_FOR_DELEGATION, cuando Administrator se conecta a SQL01 vía cualquier servicio, el KDC automáticamente incluye una copia completa del TGT de Administrator dentro del TGS que le entrega a SQL01. Esto ocurre porque el KDC ve el flag en la cuenta destino y decide "confiar" en que el servicio hará buen uso de ese TGT. Un atacante que comprometa SQL01 (con privilegios de admin local) puede leer ese TGT de la memoria del proceso LSASS y usarlo directamente — ahora tiene la identificación maestra completa de Administrator, no solo un ticket limitado a un servicio.
Constrained Delegation — ejemplo técnico
Si WEBSRV$ tiene msDS-AllowedToDelegateTo = SQL/DBSRV y protocol transition habilitado, el atacante que comprometa WEBSRV$ puede usar la extensión S4U2Self para pedirle al KDC: "dame un TGS a mí mismo, en nombre de Administrator" — sin que Administrator haya hecho nada. El KDC lo permite porque WEBSRV$ tiene el privilegio de protocol transition. Con ese TGS falso, WEBSRV$ hace una segunda petición (S4U2Proxy) pidiendo acceso a SQL/DBSRV como Administrator. El resultado final es un ticket válido para acceder a DBSRV impersonando a Administrator, generado sin que Administrator haya interactuado con nada.
RBCD — ejemplo técnico
Aquí el atacante no necesita comprometer una cuenta con delegation ya configurada — puede crearla él mismo. Si tiene GenericWrite sobre DC01$, puede escribir en msDS-AllowedToActOnBehalfOfOtherIdentity de DC01$ diciendo "confío en MACHINEFAKE$". Como MACHINEFAKE$ es una cuenta que el propio atacante controla (creada vía MachineAccountQuota), ahora puede usar S4U2Self+S4U2Proxy exactamente igual que en constrained delegation, pero habiendo configurado la confianza él mismo desde cero.
Por qué funciona (el problema de fondo)
Kerberos delegation existe porque hay un caso de uso legítimo: un servicio (como un servidor web) necesita acceder a otro recurso (como una base de datos) con los permisos exactos del usuario que inició sesión, no con permisos genéricos del servicio. El protocolo resuelve esto permitiendo que el servicio "tome prestada" la identidad del usuario.
El problema técnico es que la decisión de a quién se le permite suplantar a otros usuarios depende de un atributo configurable (TRUSTED_FOR_DELEGATION, msDS-AllowedToDelegateTo, o msDS-AllowedToActOnBehalfOfOtherIdentity), y si un atacante logra: (a) comprometer una cuenta que ya tiene delegation habilitada, o (b) obtener permisos de escritura para habilitarla él mismo, puede generar tickets Kerberos válidos impersonando a cualquier usuario del dominio — incluyendo Administrator — sin conocer su contraseña.
Ticket Forging (Golden & Silver Ticket)
Por qué funciona
Todo ticket Kerberos (TGT o TGS) es, en esencia, un blob de datos cifrado y firmado con una clave simétrica. La seguridad del sistema depende completamente de que solo el KDC conozca la clave de krbtgt (para TGTs) y solo cada servicio conozca su propia clave (para TGS tickets). El protocolo en sí no tiene forma de verificar "quién" generó el ticket — solo verifica que el ticket pueda descifrarse correctamente con la clave esperada.
Esto significa que si un atacante obtiene esas claves (hashes NTLM o AES), puede construir el ticket desde cero con cualquier contenido que quiera (usuario, grupos, fecha de expiración) y cifrarlo/firmarlo él mismo. El servicio o el KDC que reciba ese ticket no tiene manera de distinguirlo de uno legítimo, porque la única prueba de autenticidad es "¿el ticket descifra correctamente con mi clave?" — y si el atacante usó la clave correcta, la respuesta es sí.
Golden Ticket — ejemplo técnico
El atacante obtiene el hash de krbtgt (típicamente vía DCSync, que requiere permisos de replicación de dominio). Con Mimikatz kerberos::golden, construye un TGT desde cero: dice "este ticket es para Administrator, pertenece al grupo 512 (Domain Admins), y expira en 10 años", y lo cifra con el hash de krbtgt. Cuando este TGT se presenta a cualquier DC del dominio para pedir un TGS, el DC lo descifra con su copia de la clave de krbtgt, obtiene una estructura válida, y confía en el contenido — sin verificar si ese TGT fue realmente emitido en algún momento.
Silver Ticket — ejemplo técnico
Igual concepto pero un nivel más abajo: en vez de forjar el TGT, se forja directamente el TGS para un servicio específico, usando la clave de esa cuenta de servicio (por ejemplo, el hash NTLM de SQL01$). El ticket resultante nunca pasa por el KDC — se presenta directamente al servicio SQL01, que lo descifra con su propia clave de máquina y confía en el PAC falso que dice "este usuario es Administrator". Como el KDC nunca ve esta transacción, no queda registro en los logs del Domain Controller — solo en el host objetivo.
Recon y Password Spraying
Por qué funciona
El AS-REQ es la única fase de Kerberos que no requiere que el cliente ya esté autenticado — es, por definición, el primer contacto entre el cliente y el KDC. Esto lo convierte en un canal ideal para probar información sin comprometer nada todavía, porque el KDC necesariamente tiene que responder de alguna forma a una petición de un cliente desconocido.
La clave técnica es que el código de error que devuelve el KDC revela información específica sobre el estado de la cuenta, incluso sin haber completado la autenticación:
KDC_ERR_C_PRINCIPAL_UNKNOWN— El KDC buscó el nombre de usuario en su base de datos (Active Directory) y no lo encontró. Esto confirma que el username no existe, sin haber revelado nada sobre contraseñas.KDC_ERR_PREAUTH_REQUIRED— El KDC encontró el usuario y le está pidiendo el authenticator (paso normal de pre-autenticación). Esto confirma que el usuario sí existe, independientemente de si la contraseña que se probó después es correcta o no.KDC_ERR_PREAUTH_FAILED— El atacante envió un authenticator (cifrado con una contraseña candidata) y el KDC no pudo descifrarlo correctamente con la clave real del usuario. Esto confirma que el usuario existe pero la contraseña probada es incorrecta. Comparado con intentar autenticación SMB o LDAP tradicional, Kerberos permite hacer esta verificación con un solo paquete UDP por intento (mucho más rápido), y en el caso de la enumeración pura (KDC_ERR_C_PRINCIPAL_UNKNOWNvsKDC_ERR_PREAUTH_REQUIRED) no incrementa el contador de intentos fallidos de la cuenta, porque técnicamente no se llegó a intentar una autenticación real — solo se preguntó si el usuario existe.
Ejemplo del flujo
- El atacante envía
AS-REQparanoexiste123→ KDC respondeKDC_ERR_C_PRINCIPAL_UNKNOWN→ usuario descartado, sin riesgo de bloqueo. - Envía
AS-REQparajenna.smith→ KDC respondeKDC_ERR_PREAUTH_REQUIRED→ usuario confirmado como válido. - Ahora, con la lista de usuarios válidos, envía
AS-REQcon un authenticator cifrado usando la contraseña candidataSummer2024!parajenna.smith→ si el KDC responde con éxito (AS-REP válido), la contraseña era correcta. Si respondeKDC_ERR_PREAUTH_FAILED, era incorrecta — pero esta vez sí cuenta como intento fallido de login, por lo que puede contribuir al lockout de la cuenta.