¿Está sufriendo un ataque? Solicite respuesta a incidentes

info@angelforce.eu
Desarrollo seguro

Errores de seguridad con JWT y cómo evitarlos

Errores habituales con JWT: alg none, confusión RS256/HS256, secretos HMAC débiles, claims sin validar, inyección en kid, revocación y almacenamiento.

También en:EnglishTürkçeDeutschFrançaisItalianoPolskiNederlandsEesti

Ilustración: Errores de seguridad con JWT y cómo evitarlos

Los JSON Web Tokens (JWT) se usan mucho para la autenticación de API y el inicio de sesión único. El formato es sencillo, pero deja muchas decisiones de seguridad en manos del desarrollador y de la biblioteca. El RFC 8725, que recoge las buenas prácticas actuales para JWT (JWT Best Current Practices), reúne los errores conocidos y cómo evitarlos; en este artículo repasamos los que comprobaríamos en primer lugar.

Un JWT está firmado, no es secreto

Un JWT firmado, definido en el RFC 7519, tiene tres partes separadas por puntos: una cabecera, un payload con los claims y una firma. Las dos primeras solo están codificadas en base64url. Cualquiera que tenga el token puede leerlas. Este es un ejemplo decodificado:

{
  "alg": "RS256",
  "typ": "at+jwt",
  "kid": "2026-10-key-1"
}
{
  "iss": "https://auth.example.eu",
  "sub": "user-4821",
  "aud": "api.example.eu",
  "iat": 1792140000,
  "exp": 1792140900,
  "role": "editor"
}

La firma demuestra que los claims no se han modificado. No los oculta. El RFC 7519 indica que, cuando un token contiene información sensible para la privacidad, deben tomarse medidas para impedir su divulgación, por ejemplo usando un JWT cifrado (JWE). En la práctica, no incluya en el payload datos personales, identificadores internos que no publicaría ni nada secreto.

Error 1: aceptar "alg": "none"

El RFC 7519 permite JWT «no protegidos» con "alg": "none" y una firma vacía. El RFC 8725 describe bibliotecas que aceptaban estos tokens y se saltaban por completo la comprobación de la firma. Un atacante podía entonces escribir los claims que quisiera.

El RFC 7518 establece que las implementaciones no deben aceptar tokens no protegidos por defecto, y la OWASP REST Security Cheat Sheet indica que no se permitan en absoluto. Compruebe que su biblioteca rechaza none y pruébelo con un token manipulado.

Error 2: dejar que el token elija el algoritmo

El valor alg de la cabecera lo elige quien creó el token, que puede ser un atacante. El RFC 8725 describe el clásico ataque de confusión: un servidor espera RS256, verificado con una clave pública RSA. El atacante cambia alg a HS256 y firma el token con HMAC, usando esa clave pública como secreto. Una biblioteca que obedece a la cabecera lo verifica sin problemas, y la clave pública es, por definición, pública.

La solución es decidir el algoritmo en el servidor. OWASP indica que la verificación no debe depender de la cabecera del JWT para elegir el algoritmo. El RFC 8725 añade que cada clave debe usarse con exactamente un algoritmo. En código, tiene un aspecto parecido a este:

verify(token,
       key        = issuer_public_key,
       algorithms = ["RS256"],
       issuer     = "https://auth.example.eu",
       audience   = "api.example.eu")

Error 3: secretos HMAC débiles

Con HS256, cualquiera que capture un token puede intentar adivinar el secreto sin conexión, tan rápido como le permita su hardware. El RFC 8725 establece que las contraseñas memorizables por personas no deben usarse directamente como claves HMAC. El RFC 7518 exige una clave al menos tan larga como la salida del hash, es decir, 256 bits para HS256.

openssl rand -base64 32

Esto genera 32 bytes aleatorios, es decir, 256 bits. Guárdelos en un gestor de secretos, no en el repositorio.

Los secretos compartidos tienen una segunda debilidad. Todo servicio que puede verificar un token HMAC también puede crear uno. Por eso OWASP prefiere las firmas a los MAC: si varios servicios validan tokens, de lo contrario un solo servicio comprometido podría emitir tokens para todos ellos. Los algoritmos asimétricos, como RS256 o ES256, le permiten compartir solo la clave pública.

Error 4: no validar los claims

Una firma válida solo demuestra quién emitió el token. Los claims deciden si este servicio debe aceptarlo ahora.

  • exp: el RFC 7519 indica que el token no debe aceptarse en ese momento ni después. Se permite un pequeño margen por la desviación de los relojes, normalmente de no más de unos minutos.
  • nbf: si está presente, rechace el token antes de ese momento.
  • iss: compruebe que el emisor es el de su confianza y que es el propietario de la clave de firma.
  • aud: el RFC 7519 indica que, si el servicio no se encuentra a sí mismo entre los destinatarios, el token debe rechazarse.

OWASP recomienda exigir y validar iss, aud y exp por defecto en los tokens de acceso a API. El RFC 8725 explica por qué importa el destinatario. Sin él, un token emitido para un servicio puede reutilizarse en otro que confíe en el mismo emisor. También recomienda tipar los tokens de forma explícita con la cabecera typ, para que un tipo de token no pueda usarse donde se espera otro. Para los tokens de acceso de OAuth, el RFC 9068 usa at+jwt, como en el ejemplo anterior.

Error 5: fiarse de kid, jku y x5u

Los parámetros de la cabecera que indican al servidor dónde encontrar la clave también los controla el atacante. El RFC 8725 enumera los riesgos:

  • kid (ID de clave), si se usa en una búsqueda en una base de datos o un directorio, puede permitir una inyección SQL o LDAP. Lo mismo ocurre si se usa para construir una ruta de archivo.
  • jku y x5u apuntan a una URL desde la que descargar claves. Seguir cualquier URL permite la falsificación de peticiones del lado del servidor (SSRF), y un atacante podría apuntarla a su propia clave.

Trate kid como una etiqueta opaca y búsquela en una lista fija de claves que usted controle. Descargue claves solo de una lista de URL permitidas; el RFC 8725 añade que esas peticiones no deben enviar cookies.

Error 6: tokens de larga duración y sin revocación

Un JWT sigue siendo válido hasta que caduca, aunque el usuario cierre la sesión o un administrador desactive la cuenta. OWASP señala que los tokens pueden sobrevivir a la sesión que representan.

  • Mantenga los tokens de acceso de corta duración: minutos, no días.
  • Use tokens de actualización que el servidor compruebe en cada uso y pueda revocar.
  • Para los cierres de sesión y las suspensiones de cuentas, mantenga una lista de bloqueo de identificadores de token (jti) hasta que esos tokens caduquen, como sugiere OWASP.
  • Rote las claves de firma de forma periódica y tenga un proceso probado para una rotación de emergencia.

Error 7: guardar los tokens donde los scripts pueden leerlos

Los tokens guardados en localStorage pueden leerse desde cualquier JavaScript de la página. La OWASP HTML5 Security Cheat Sheet advierte de que un solo fallo de cross-site scripting puede robar todo lo que hay en estos objetos de almacenamiento, y desaconseja guardar ahí identificadores de sesión.

En las aplicaciones de navegador, una cookie HttpOnly y Secure con un ajuste SameSite adecuado mantiene el token fuera del alcance de los scripts. Las cookies hacen entrar en juego la falsificación de peticiones entre sitios (CSRF), así que téngala también en cuenta. Elija lo que elija, una Content Security Policy sólida reduce de entrada la probabilidad de XSS.

Lista de comprobación para la validación

  1. Fije en el servidor los algoritmos aceptados y rechace none.
  2. Use una biblioteca que verifique la firma antes de leer cualquier claim.
  3. Valide exp, nbf, iss y aud en cada petición.
  4. Use typ o destinatarios distintos para separar los tipos de token.
  5. Busque las claves por kid en un conjunto fijo; nunca descargue claves de URL arbitrarias.
  6. Use claves HMAC aleatorias de al menos 256 bits, o claves asimétricas.
  7. No incluya en los payloads secretos ni datos personales innecesarios.
  8. Mantenga los tokens de acceso de corta duración y permita su revocación.
  9. Guarde los tokens del navegador fuera del alcance de JavaScript.

Por dónde empezar

Pegue un token de su entorno de pruebas en nuestro decodificador JWT para ver exactamente qué revela, y compare sus valores alg, aud y exp con esta lista. No pegue tokens de producción en uso en ninguna herramienta en línea.

Si quiere una segunda opinión sobre el diseño de su autenticación o una revisión del código que gestiona los tokens, nuestro equipo de desarrollo de software seguro puede ayudarle.

Cómo podemos ayudarle

Software seguro

Integramos la seguridad en el software desde el primer commit y desarrollamos nuestras propias herramientas de seguridad.

Decodificador JWT

Decodifique un JSON Web Token y busque errores de seguridad habituales, sin que salga de su navegador.

Contacte con nosotros
Equipo de AngelForce

Escrito por el equipo de AngelForce: consultores de seguridad con certificaciones CEH, LPT Master y CISA que prueban, supervisan y protegen los sistemas de organizaciones de toda Europa y Türkiye.

Redactado con ayuda de IA a partir de las fuentes públicas que se indican más abajo y revisado por el equipo de AngelForce antes de su publicación.

Fuentes

  1. datatracker.ietf.org/doc/html/rfc7519
  2. datatracker.ietf.org/doc/html/rfc8725
  3. datatracker.ietf.org/doc/html/rfc7518
  4. cheatsheetseries.owasp.org/cheatsheets/REST_Security_Cheat_Sheet.html
  5. cheatsheetseries.owasp.org/cheatsheets/HTML5_Security_Cheat_Sheet.html

Artículos sobre Desarrollo seguro

Cuéntenos qué necesita proteger

Describa su entorno y lo que quiere conseguir. Le responderemos por correo electrónico.

Contacte con nosotros
info@angelforce.eu

AngelForce OÜ · Tallinn, Estonia