
Muchas aplicaciones usan JSON Web Tokens (JWT) para permitir que el cliente se identifique para un mayor intercambio de información después de la autenticación.
JSON Web Token es un estándar abierto (RFC 7519) que define una forma compacta e independiente de transferir información de forma segura entre las partes como un objeto JSON.

Esta información es verificada y confiable porque está firmada digitalmente.
Los JWT se pueden firmar usando un secreto (usando el algoritmo HMAC) o pares de claves públicas / privadas usando RSA o ECDSA.
JSON Web Token se utiliza para transmitir información sobre la identidad y las características del cliente. Este "contenedor" está firmado por el servidor para que el cliente no interfiera con él y no pueda cambiar, por ejemplo, los datos de identificación o cualquier característica (por ejemplo, el rol de un usuario simple a un administrador o cambiar el inicio de sesión del cliente).
Este token se crea en caso de autenticación exitosa y el servidor lo verifica antes de iniciar cada solicitud del cliente. La aplicación utiliza el token como una "tarjeta de identidad" del cliente (un contenedor con toda la información sobre él). El servidor tiene la capacidad de verificar la validez e integridad del token de manera segura. Esto permite que la aplicación no tenga estado (la aplicación sin estado no guarda los datos del cliente generados en una sesión para usar en la próxima sesión con este cliente (cada sesión es independiente)), y el proceso de autenticación es independiente de los servicios utilizados (en el sentido de que las tecnologías de cliente y servidor puede variar, incluso el canal de transporte, aunque HTTP se usa con mayor frecuencia).
Consideraciones para usar JWT
Incluso si el token JWT es fácil de usar y le permite proporcionar servicios (principalmente REST) sin estado (sin estado), esta solución no es adecuada para todas las aplicaciones, ya que viene con algunas advertencias, como el problema de almacenar el token.
Si la aplicación no tiene que estar completamente sin estado, entonces puede considerar usar el sistema de sesión tradicional proporcionado por todas las plataformas web. Sin embargo, para aplicaciones sin estado, JWT es una buena opción si se implementa correctamente.
Problemas y ataques de JWT
Usando el Algoritmo Hash NINGUNO
Un ataque similar ocurre cuando un atacante cambia el token y también cambia el algoritmo de hashing (campo "alg") para indicar a través de la palabra clave none que la integridad del token ya ha sido verificada. Algunas bibliotecas vieron tokens firmados usando el algoritmo none como un token válido con una firma verificada, por lo que un atacante podría cambiar la carga útil del token, y la aplicación confiaría en el token.
Para evitar un ataque, debe usar la biblioteca JWT, que no se ve afectada por esta vulnerabilidad. Además, durante la validación del token, debe solicitar explícitamente el uso del algoritmo esperado.
Ejemplo de implementación:
Intercepción de tokens
El ataque ocurre cuando un atacante ha interceptado o robado un token y este lo utiliza para obtener acceso al sistema utilizando las credenciales de un usuario específico.
La protección consiste en agregar un "contexto de usuario" al token. El contexto del usuario consistirá en la siguiente información:
- Una cadena aleatoria que se genera en la etapa de autenticación y se incluye en el token, y también se envía al cliente como una cookie más segura (marcas: HttpOnly + Secure + SameSite + prefijos de cookies).
- El hash SHA256 de la cadena aleatoria se almacenará en el token para que cualquier problema de XSS no permita al atacante leer el valor de la cadena aleatoria y establecer la cookie esperada.
La dirección IP no se usará en contexto, porque hay situaciones en las que la dirección IP puede cambiar durante una sesión, por ejemplo, cuando un usuario accede a la aplicación a través de su teléfono móvil. Entonces, la dirección IP cambia constantemente de manera legítima. Además, el uso de una dirección IP puede causar problemas a nivel de cumplimiento con el GDPR europeo.
Si durante la verificación del token el token recibido no contiene el contexto correcto, debe ser rechazado.
Ejemplo de implementación:Código para crear un token después de una autenticación exitosa:
Código para verificar la validez del token:
Revocación explícita de token por usuario
Dado que el token se vuelve inválido solo después de su vencimiento, el usuario no tiene una función incorporada que le permita cancelar explícitamente el token. Por lo tanto, en caso de robo, el usuario no puede retirar la ficha por sí mismo y luego bloquear al atacante.
Uno de los métodos de protección es la introducción de una lista negra de tokens, que será adecuada para simular la función de "cerrar sesión" que existe en un sistema de sesión tradicional.
La colección (en la codificación SHA-256 en HEX) del token con la fecha de cancelación, que debe exceder el período de validez del token emitido, se almacenará en la lista negra.
Cuando el usuario quiere "cerrar sesión", llama a un servicio especial que agrega el token de usuario proporcionado a la lista negra, lo que lleva a la cancelación inmediata del token para su uso posterior en la aplicación.
Ejemplo de implementación:Repositorio de la lista negra:Para el almacenamiento centralizado de la lista negra, se utilizará una base de datos con la siguiente estructura:
create table if not exists revoked_token(jwt_token_digest varchar(255) primary key, revokation_date timestamp default now());
Gestión de revocación de tokens:
Divulgación de tokens
Este ataque ocurre cuando un atacante obtiene acceso a un token (o un conjunto de tokens) y extrae la información almacenada en él (la información sobre el token JWT se codifica usando base64) para obtener información sobre el sistema. La información puede ser, por ejemplo, como roles de seguridad, formato de inicio de sesión, etc.
El método de protección es bastante obvio y consiste en cifrar el token. También es importante proteger los datos cifrados de los ataques mediante criptoanálisis. Para lograr todos estos objetivos, se utiliza el algoritmo AES-GCM, que proporciona cifrado autenticado con datos asociados (AEAD). La primitiva AEAD proporciona una funcionalidad de cifrado simétrico autenticado. Las implementaciones de esta primitiva están protegidas de ataques adaptativos basados en texto cifrado seleccionado. Al cifrar texto sin formato, opcionalmente puede especificar datos relacionados que deben autenticarse pero no cifrarse.
Es decir, el cifrado con los datos relevantes garantiza la autenticidad e integridad de los datos, pero no su secreto.
Sin embargo, debe tenerse en cuenta que el cifrado se agrega principalmente para ocultar información interna, pero es muy importante recordar que la protección inicial contra la falsificación del token JWT es la firma, por lo tanto, la firma del token y su verificación siempre deben usarse.
Almacenamiento de token del lado del cliente
Si la aplicación almacena el token para que ocurra una o más de las siguientes situaciones:
- el token es enviado automáticamente por el navegador (almacenamiento de cookies);
- el token se obtiene incluso si se reinicia el navegador (usando el contenedor localStorage del navegador);
- el token se obtiene en el caso de un ataque XSS (cookie disponible para código JavaScript o un token que se almacena en localStorage o sessionStorage).
Para evitar un ataque:
- Almacene el token en el navegador utilizando el contenedor sessionStorage.
- Agréguelo al encabezado de Autorización usando el esquema Portador. El título debería verse así:
Authorization: Bearer <token>
- Agregue información de huella digital al token.
Al almacenar el token en el contenedor sessionStorage, proporciona un token para robo en el caso de XSS. Sin embargo, una huella digital agregada al token evita que un atacante reutilice el token robado en su computadora. Para cerrar las áreas de uso máximo para un atacante, agregue una Política de seguridad de contenido para limitar el contexto de ejecución.
Sigue habiendo un caso en el que un atacante usa el contexto de navegación del usuario como un servidor proxy para usar la aplicación de destino a través de un usuario legítimo, pero la Política de seguridad de contenido puede evitar la comunicación con dominios inesperados.
También es posible implementar un servicio de autenticación para que el token se emita dentro de una cookie segura, pero en este caso, se debe implementar protección contra CSRF.
Usar una tecla débil para crear un token
Si el secreto utilizado en el caso del algoritmo HMAC-SHA256, necesario para firmar el token, es débil, entonces puede ser pirateado (recogido mediante ataque de fuerza bruta). Como resultado, un atacante puede falsificar un token válido arbitrario en términos de una firma.
Para evitar este problema, debe usar una clave secreta compleja: alfanumérica (mayúsculas y minúsculas) + caracteres especiales.
Dado que la clave solo es necesaria para los cálculos por computadora, el tamaño de la clave secreta puede superar las 50 posiciones.
Por ejemplo:
A&'/}Z57M(2hNg=;LE?~]YtRMS5(yZ<vcZTA3N-($>2j:ZeX-BGftaVk`)jKP~q?,jk)EMbgt*kW'
Para evaluar la complejidad de la clave secreta utilizada para la firma del token, puede aplicar un ataque de diccionario de contraseña al token en combinación con la API JWT.