
EXPLOTACIÓN DE JWT POR INYECCIÓN DE CABECERA JWK
Introducción a JWT y sus componentes
JSON Web Token (JWT) es un estándar ampliamente utilizado para transmitir información segura entre partes, especialmente en procesos de autenticación y autorización en aplicaciones web. Un JWT consta de tres partes: cabecera (header), carga útil (payload) y firma (signature).
Componente | Descripción |
---|---|
Header | Contiene el tipo de token (JWT) y el algoritmo de firma (como RS256). |
Payload | Incluye los datos y declaraciones del usuario (claims). |
Signature | Verifica que el mensaje no fue alterado y que proviene de una fuente confiable. |
Este sistema es especialmente robusto cuando se implementa con cifrado asimétrico, donde intervienen una clave pública y una privada.
Parámetros críticos en la cabecera JWT
La cabecera de un JWT puede contener campos adicionales que, aunque útiles, pueden ser explotados si se implementan sin las debidas precauciones. Entre los parámetros más delicados se encuentran:
Parámetro | Nombre completo | Descripción |
---|---|---|
kid |
Key ID | Identificador de la clave utilizada para firmar el token. |
jku |
JWK Set URL | URL de donde se puede obtener la clave pública para verificar la firma. |
jwk |
JSON Web Key | Clave pública embebida directamente en la cabecera del token. |
La incorrecta validación o confianza implícita en estos valores puede conducir a vulnerabilidades graves.
Claves asimétricas en JWT
El JWT suele utilizar criptografía asimétrica, lo que implica el uso de dos claves diferentes:
- Clave privada: Reservada al firmante (por ejemplo, un servidor).
- Clave pública: Compartida y usada para verificar la autenticidad del token.
La firma de un JWT debe ser verificada únicamente con claves públicas confiables. Sin embargo, cuando se aceptan claves sin la validación apropiada, se abre la puerta a ataques de inyección.
Comprendiendo el ataque: JWK Header Injection
En ciertas implementaciones vulnerables, el servidor permite que un atacante especifique su propia clave pública dentro del campo jwk
del header JWT. Esto da lugar a un escenario en el que:
- El atacante genera su propio par de claves (RSA).
- Firma un token falsificado con su clave privada.
- Inserta su clave pública en el
jwk
del header. - El servidor acepta el token porque la firma es válida con respecto a la clave especificada.
Este vector de ataque se denomina JWT Authentication Bypass via JWK Header Injection.
Condiciones necesarias para explotar la vulnerabilidad
Para que este ataque sea factible, deben cumplirse ciertas condiciones:
- El servidor acepta claves públicas del campo
jwk
sin validarlas contra una lista segura. - El algoritmo de firma utilizado es uno asimétrico como
RS256
. - El campo
kid
ojwk
no está siendo validado contra una fuente segura o una lista blanca.
El mal uso del parámetro ‘jwk’ permite a un atacante firmar sus propios tokens válidos.
Escenario de explotación paso a paso
Veamos un flujo de ataque típico:
- El atacante se registra normalmente en la aplicación y obtiene un JWT válido.
- Utilizando herramientas como Burp Suite o JWT Editor, genera un nuevo par RSA (clave pública y privada).
- Crea un nuevo JWT falsificado, cambiando el
sub
(sujeto) del token a “administrator” y firmándolo con su clave privada. - Inserta su clave pública directamente en la cabecera usando el campo
jwk
. - Envía el token al servidor.
- Si el servidor es vulnerable, aceptará el token como válido, otorgando acceso a privilegios de administrador.
Esto demuestra cómo un atacante puede convertirse en administrador sin tener las credenciales reales.
Ejemplo de cabecera con JWK inyectado
{
"alg": "RS256",
"typ": "JWT",
"jwk": {
"kty": "RSA",
"kid": "attacker-key",
"use": "sig",
"n": "MIIBIjANBgkq...",
"e": "AQAB"
}
}
Y el payload alterado:
{
"sub": "administrator",
"iat": 1629999999
}
El token se firma con la clave privada correspondiente al n
y e
provistos.
Herramientas para facilitar la explotación
Algunas herramientas útiles para reproducir este ataque incluyen:
- Burp Suite con la extensión JWT Editor.
- jwt.io para visualizar y editar tokens.
- OpenSSL para generar pares de claves RSA.
- Scripts personalizados en Python o Node.js para automatizar el proceso de generación, firma e inyección.
Generación de claves con OpenSSL
openssl genrsa -out private.key 2048
openssl rsa -in private.key -pubout -out public.key
Luego, convertir a formato JWK:
# Usar alguna herramienta o script para convertir public.key a formato JWK
Una mala validación en el servidor permite autenticarse como cualquier usuario.
Prácticas seguras para evitar esta vulnerabilidad
Para prevenir este tipo de ataque, los desarrolladores deben adoptar las siguientes medidas:
- Validar siempre la clave pública contra una lista predefinida o extraída desde un
jku
confiable. - Rechazar cualquier token que contenga un campo
jwk
si no es esperado. - Verificar que el
kid
haga referencia a una clave conocida y almacenada localmente o en un proveedor de confianza. - No permitir la modificación dinámica del header JWT por parte del cliente.
- Establecer reglas estrictas en el verificador JWT del backend (por ejemplo, usando bibliotecas que no permitan claves externas por defecto).
Conclusiones
La técnica de inyección de cabecera JWK representa una amenaza crítica en sistemas que usan JWT para autenticación. El permitir que los clientes definan su propia clave pública en el header del token rompe por completo el modelo de confianza del sistema.
A través de esta vulnerabilidad, un atacante puede obtener acceso administrativo sin necesidad de conocer credenciales reales, simplemente aprovechando la validación insegura de claves. Como se ha demostrado, el uso indebido del parámetro jwk
puede ser fatal para la integridad de cualquier sistema de autenticación basado en JWT.
La forma más segura de prevenir este tipo de ataques es mantener un control estricto sobre las claves públicas válidas y nunca aceptar claves proporcionadas por el usuario sin validación rigurosa.
Implementaciones seguras de JWT deben asumir que todo lo que proviene del cliente puede ser manipulado.