jueves, 31 de mayo de 2018

JWT 1

Buenas noches, si me pase mas de un mes sin postear, la verdad si lo deseaba pero por temas de trabajo que a uds siempre les menciono, me alejo un poco, pero bueno ya estoy de vuelta, vamos con todo.
Ya seguramente algunos desarrolladores han implementado la autenticación por token JWT(jason web token).

Background:
Este token es una firma cifrada, que permite al API identificar a nuestros usuarios. Este token se produce  del lado cliente y el mismo API es el que se encarga de decifralo, es decir no se guarda en el servidor. Esto permite tener una gran escalabilidad para entornos web y mobiles.
La composicion es de 3 cadenas separadas por ".":

GET /index.php HTTP/1.1
Host: atacamejwt.com
User-Agent: Mozilla/5.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: http://atacamejwt.com/register.php
Cookie: auth=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXUyJ9.eyJsb2dpbiI6InVzZXIxIiwiaWF0IjoiMTUyNzgxODM4OCJ9.YTI2Y2UyM2FkMjcyOTA4ZGMzZDEwZjA1ODFlMTYwMmIwYjM5ZTY5MTRkMWU4NjUyMmUzN2VkYmQzMTZjZDg2Nw
Connection: close

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXUyJ9.eyJsb2dpbiI6InVzZXIxIiwiaWF0IjoiMTUyNzgxODM4OCJ9.YTI2Y2UyM2FkMjcyOTA4ZGMzZDEwZjA1ODFlMTYwMmIwYjM5ZTY5MTRkMWU4NjUyMmUzN2VkYmQzMTZjZDg2Nw

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXUyJ9 = header
eyJsb2dpbiI6InVzZXIxIiwiaWF0IjoiMTUyNzgxODM4OCJ9=Payload
YTI2Y2UyM2FkMjcyOTA4ZGMzZDEwZjA1ODFlMTYwMmIwYjM5ZTY5MTRkMWU4NjUyMmUzN2VkYmQzMTZjZDg2Nw = Firma
La primera es el header, se decodificamos en base 64 podemos ver lo siguiente:
{"alg":"HS256","typ":"JWS"}
Esta compuesto por el algoritmo cryptografico HMAC256, que asegura la integridad pero puede escojer otro algoritmo, si miremos:

  • RSA based
  • Elliptic curves
  • HMAC
  • None
Bueno aqui esta el detalle el valor "None", que es lo que hace este valor, como menciona, hace que no lleve ninguna firma, probablemente su implementacion fue para realizar un debug a la aplicación

La segunda es el payload, si decoficamos en base 64:
{"login":"user1","iat":"1527818388"}
Podemos observar que se compone por el usuario que se esta logeando a la aplicación y un valor IAT, el cual refleja cuando el JWT fue emitido, osea no es algun identificador.
La tercera es la firma, que se conforma por el header y el payload mas una clave secreta que se localiza en el servidor, aqui otra posible vulnerabilidad

Al ataque:
El primer vistazo de la autenticación de un usuario, que lo denominaremos "user1" es la siguiente:
Vemos que se usa el token JWT para producir una sesion con "user1"


Pero que pasa si alteramos este token, pensemos.
Que pasa si decodifico el header y cambio el valor de "HS256" por un None, esto a que me sujeta, a que se anule la firma que contiene una clave secreta, que para obtenerla tendria practicamente que haber comprometido previamente todo el backend.
hacemos lo siguiente:
{"alg":"HS256","typ":"JWS"}
por:
{"alg":"None","typ":"JWS"}
ya tenemos la primera parte, ahora vayamos por más, si el usuario administrador fuera "admin", ya sin firma, ¿podemos logearnos como tal?, entonces tambien cambiemos el payload:
{"login":"user1","iat":"1527818388"}
por:
{"login":"admin","iat":"1527818388"}
Listo que queda, volver a codificar, pero ojo no olvidemos que el valor de firma deberia tener una valor nulo, entonces hacemos lo siguiente:
base64(<header>).base64(<payload>).Listo veamos cual fue el resultado:



Exactamente ahora somos el usuario "admin".
Posible solución, busquemos librerias donde no se use el "None"  o que durante la validación se verfique el algoritmo usado.
https://www.owasp.org/index.php/JSON_Web_Token_(JWT)_Cheat_Sheet_for_Java#NONE_hashing_algorithm
Bueno, un gusto otra vez.

No hay comentarios:

Publicar un comentario