Vulnerabilidades JWT
Última actualización
¿Te fue útil?
Última actualización
¿Te fue útil?
Es un estándar basado en JSON (Javascript Object Notation) para la creación de tokens de acceso que permiten la propagación de identidad y privilegios. El token está firmado por la clave del servidor, así que el cliente y el servidor son ambos capaces de verificar que el token es legítimo.
Los JSON Web Tokens están diseñados para ser compactos, poder ser enviados en las URLs -URL-safe- y ser utilizados en escenarios de (SSO).
El estándar de JWT se basa en otros estándares basados en JSON () y ()
JWT = Datos en JSON criptográficamente firmados
JWE = JWT encriptado
Consideraciones:
Utilizar JWT previene de los ataques CSRF. Pero puede seguir siendo vulnerable si se almacena en una cookie.
Si se almacena en local storage, es susceptible a ataques XSS.
Los JWTs son buenos contra ataques de dominio cruzado (cross domain).
Están formados por 3 partes:
Una cabecera o header. Indentifica el algoritmo utilizado para generar la firma.
Algoritmos aceptados:
RSA.
HMAC.
Elliptic Curve.
None.
Un contenido o payload. Contiene los privilegios del token.
Valores:
iss: issuer
iat: issued at
nbf: “not before” (start date)
sub: subject
exp: expires at
Puede contener cualquier información, como: Nombre de usuario, email, rol, permisos, contraseñas.
Una firma digital o signature. Que se calcula codificando la cabecera y el contenido en base64, concatenándose con un punto.
Normalmente empiezan con eyJ0eXAi
o eyJhbGci
.
eyJ0eXAi
= {"typ"
eyJhbGci
= {"alg"
Y un punto en los primeros 40-60 caracteres.
Sustitución de caracteres:
+
-> -
/
-> _
=
-> ` ` (se elimina)
Ej:
Muchas librerías JWT tienen un método para decodificar y otro para verificar el token:
decode()
. Decodifica el token sin verificar la firma.
verify()
. Decodifica y verifica el token.
Durante el desarrollo suele utilizarse el método decode()
y cuando se pasa la aplicación a producción se suele olvidar cambiar el método por verify()
.
Si se cambia el algoritmo por none en alguna de sus siguientes variantes y se elimina el tercer campo del JWT dejando el punto final.
Ej:
Esta vulnerabilidad se da cuando la aplicación no comprueba que el algoritmo coincida con el algoritmo que se espera.
ALGORITMOS
Asimétrico (RSA)
Clave privada
Clave pública
Simétrico (HMAC)
Contraseña
Contraseña
Algoritmo asimétrico: Cuando se utiliza una encriptación asimétrica, se publica la clave pública y se mantiene la clave privada en secreto. Esto permite firmar el token con la clave privada y que cualquiera pueda verificarla con la clave pública.
RSA
Si la clave pública está disponible, un atacante puede falsificar tokens:
Cambiando el algoritmo del token por HMAC.
Manipulando el resultado con el payload.
Firmar el token con la clave pública detectada en la aplicación o en el JWT.
Enviar el JWT de vuelta a la aplicación.
HMAC
La fortaleza de la firma vendrá determinada por la fortaleza de la contraseña. Si la aplicación utiliza una contraseña débil, se podrá llegar a obtener por medio de fuerza bruta.
COMPROBACIÓN DEL ALGORITMO
Normalmente las librerías comprueban el algoritmo de la siguiente manera:
HMAC. verify(token, secret)
.
RSA o similar. verify(token, secret)
.
Si la cabecera contiene el parámetro kid
, este normalmente es usado para obtener la clave de una base de datos o sistema de ficheros. La aplicación verifica la firma utilizando la clave obtenida en este parámetro.
Si el parámetro es inyectable, este podría ser utilizado para saltarse la firma o realizar ataques de RCE, SQLi o LFI.
EJEMPLO
JWT Original
JWT con inyección
INYECCIÓN EN PARÁMETRO KID + DIRECTORY TRAVERSAL
Si la aplicación utiliza el parámetro kid como valor de la clave utilizada para validar la firma, un atacante podría modificarlo por un fichero con el valor de la clave, por ejemplo, /dev/null
y con ello saltársela.
Ejemplo
INYECCIÓN EN PARÁMETRO KID + INYECCIÓN SQL
Si la aplicación utiliza el parámtro kid para obtener la información de la base de datos como la clave de la firma, se podría intentar inyectar código SQL.
Ejemplo de consulta SQL
Ejemplo de inyección SQL en kid
Consulta con inyección en kid
La inyección ' UNION SELECT 'aaaa
permite a un atacante sustituir la clave por aaaa
y con ello firmar el token con dicha clave para saltarse la firma.
Ejemplo de JWT con jku
Ejemplo de JSON Web Key (fichero key.json)
FORMAS DE SALTARSE LAS LIMITACIONES
Utilizando https://xtormin
si la aplicación solo comprueba el inicio de la URL (ej: https://xtormin@attacker.com/key.json
).
Utilizando fragmentos con el caracter #
.
Utilizando la jerarquía de nombres DNS.
Concatenándolo con open redirect, header injection o ssrf.
### Prevención
Para prevenirlo, se debe:
Filtrar la URL correctamente.
Añadir los hosts permitidos en whitelist.
Prevenir otros ataques que puedan ser concatenados para saltarse las restricciones.
JSON Web Token Attacker - JOSEPH
Generalmente los algoritmos de cifrado utilizados son HMAC con (HS256) y con (RS256).
Muchas librerías no comprueban por defecto si el algoritmo coincide, por eso se utiliza la siguiente para verificarlo.
Este parámetro se utiliza para especificar el JSON Web Key Set URL (), que indica donde se encuentra el JSON Web Key utilizado para verificar la firma.
.