Skip to content
Back to Blog
jwtsecurityvulnerabilityauthentication

Explicación de los ataques JWT alg:none y de confusión

Dos ataques clásicos a JWT, alg:none y confusión RS256 a HS256, explotan servidores que confían en el encabezado alg. Explicamos cada ataque paso a paso y la solución de lista blanca que los detiene.

SZ
Founder, Molixa
11 min read
Compartir
Explicación de los ataques JWT alg:none y de confusión
Table of contents6 sections

La vulnerabilidad del algoritmo 'none' en JWT permite a un atacante eliminar la firma de un token y reescribir su contenido, y el servidor acepta el token falsificado como válido. Ocurre cuando tu código confía en el campo alg dentro del encabezado del token en lugar de decidir el algoritmo por ti mismo. La misma causa raíz impulsa el ataque de confusión RS256 a HS256. Ambos son evasiones de autenticación, y ambos se solucionan con una línea de código.

Si implementas JSON Web Tokens, este es uno de los pocos errores de seguridad que convierte una molestia de solo lectura en una toma de control total de la cuenta. Un atacante que pueda falsificar un token válido puede establecer "sub": "admin", no firmar nada, y acceder. A continuación verás exactamente cómo funciona cada ataque, con los bytes detallados, además de la corrección con lista blanca que elimina toda esta clase de error.

Qué es realmente la vulnerabilidad del algoritmo None en JWT#

Un JWT tiene tres partes separadas por puntos: un encabezado en base64url, un payload en base64url y una firma. El encabezado declara qué algoritmo firmó el token, como {"alg":"HS256","typ":"JWT"}. La firma es lo que demuestra que el token no ha sido manipulado.

El algoritmo none es una parte legítima de la especificación JWT (RFC 7519). Significa que el token no está firmado. Existe para situaciones donde la capa de transporte ya garantiza la integridad, por lo que la firma está intencionalmente vacía. El problema no es que none exista. El problema es cuando una librería de verificación trata el encabezado alg: none del propio token como permiso para omitir la verificación de firma por completo.

La falla central en ambos ataques a continuación es idéntica: el servidor lee el encabezado alg controlado por el atacante y confía en él para decidir cómo (o si) verificar la firma. Nunca permitas que una entrada no confiable elija tu algoritmo de verificación.

La falsificación en tres pasos#

Aquí está el ataque contra un servidor que honra alg: none. Supongamos que un token real se decodifica a este payload:

{ "sub": "1234", "role": "user", "exp": 1735689600 }

Un atacante hace tres cosas:

  1. Cambia el encabezado a {"alg":"none","typ":"JWT"} y lo codifica en base64url.
  2. Edita el payload a {"sub":"1","role":"admin","exp":9999999999} y lo codifica.
  3. Elimina la firma, dejando el token terminando en un punto final sin nada después.

El token falsificado se ve así: eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0.eyJzdWIiOiIxIiwicm9sZSI6ImFkbWluIn0. (nota el punto colgante). Un servidor vulnerable decodifica el encabezado, ve none, omite la verificación y concede acceso de administrador. Sin secreto, sin clave, sin descifrado. Puedes pegar cualquier token en nuestro decodificador JWT gratuito para ver exactamente qué encabezado alg lleva antes de confiar en él.

Por qué "none" a veces tiene una N mayúscula#

Algunas librerías antiguas bloqueaban de forma sensible a mayúsculas la cadena none pero no None, NONE o nOnE. Debido a que la especificación JWT trata los nombres de algoritmos de forma sensible a mayúsculas pero el código real no siempre lo hacía, los atacantes eludían listas negras ingenuas variando las mayúsculas. Esta es la primera lección de seguridad JWT: una lista negra de valores malos es frágil. Una lista blanca de valores buenos no lo es.

El ataque de confusión de algoritmo RS256 a HS256#

El ataque de confusión es más sigiloso y aún sorprende a los equipos en 2026. Explota la diferencia entre la firma simétrica y asimétrica cuando una sola llamada de verificación acepta ambas.

Dos familias de algoritmos importan aquí:

  • HS256 es simétrico. Un secreto compartido firma y verifica. Quien tenga el secreto puede crear tokens válidos.
  • RS256 es asimétrico. Una clave privada firma y una clave pública verifica. La clave pública es, por diseño, pública. Está bien publicarla.

Un servidor que usa RS256 mantiene su clave privada bajo llave y verifica los tokens entrantes con la clave pública. Eso es seguro, siempre que el servidor solo ejecute verificación RS256.

Cómo la clave pública se convierte en un secreto para falsificar#

La confusión ocurre cuando el código de verificación se ve más o menos así:

// VULNERABLE: algoritmo tomado del encabezado del token
jwt.verify(token, key);

Muchas bibliotecas, al recibir un token, leen el encabezado alg para elegir la ruta de verificación. Si el sistema original es RS256, el atacante hace esto:

  1. Obtiene la clave pública RSA. A menudo está expuesta en un endpoint JWKS, en una URL .well-known, en un SDK o simplemente publicada en la documentación.
  2. Falsifica un token con el encabezado cambiado a {"alg":"HS256"} y un payload elevado.
  3. Firma ese token con HMAC-SHA256, usando los bytes exactos de la clave pública como secreto HMAC.

Ahora el servidor recibe un token HS256. Toma su clave RSA (que creía que solo era una clave de verificación) y ejecuta HMAC con ella. Como el atacante firmó con esa misma cadena de clave pública, el HMAC coincide. La firma se verifica. El token de administrador falsificado es aceptado.

El atacante convirtió tu clave pública inofensiva y publicada en el secreto que falsifica tokens. Nunca necesitaron la clave privada.

Advertencia: la parte más complicada de reproducir esto es obtener la representación exacta en bytes de la clave pública (PEM con el salto de línea final, encabezados incluidos o eliminados). Los atacantes prueban por fuerza bruta las pocas codificaciones comunes. Trata cualquier implementación RS256 que también acepte HS256 como ya comprometida.

Por qué es tan fácil incluirlo por accidente#

La vulnerabilidad casi nunca se escribe a propósito. Se cuela cuando:

  • Una biblioteca por defecto infiere el algoritmo del encabezado del token.
  • Un equipo migra de HS256 a RS256 pero deja habilitada la ruta de verificación anterior "por si acaso".
  • Una función envoltorio acepta un argumento key genérico y lo pasa al algoritmo que el token solicite.

Si quieres una mirada más profunda sobre por qué decodificar un token no es lo mismo que verificarlo, el análisis en decodificar versus verificar en seguridad JWT muestra dónde los equipos confunden ambos conceptos y abren exactamente este agujero.

La solución: lista blanca de tu algoritmo#

Ambos ataques mueren en el momento en que el servidor deja de confiar en el encabezado alg del token y, en su lugar, fija el algoritmo que aceptará. Esta es la defensa JWT más importante y, por lo general, es una sola línea.

Fija el algoritmo explícitamente#

En Node con la biblioteca común jsonwebtoken, pasa una lista blanca explícita de algorithms:

// SEGURO: solo se acepta HS256
jwt.verify(token, secret, { algorithms: ["HS256"] });

// SEGURO: solo RS256, con la clave PÚBLICA, nada más
jwt.verify(token, publicKey, { algorithms: ["RS256"] });

Con esta lista blanca, un token falsificado con alg: none es rechazado porque none no está en la lista. Un token HS256 falsificado enviado al verificador RS256 es rechazado porque el verificador solo ejecutará RS256, y los bytes HMAC no pueden satisfacer una verificación de firma RSA.

Toda biblioteca JWT madura tiene el mismo control con un nombre ligeramente diferente:

Lenguaje / BibliotecaParámetro de lista blanca
Node jsonwebtokenalgorithms: ["RS256"] en verify()
Python PyJWTalgorithms=["RS256"] en jwt.decode()
Go golang-jwtWithValidMethods([]string{"RS256"})
Java java-jwt (Auth0)construir el verificador con el Algorithm específico
PHP firebase/php-jwtpasar el algoritmo a JWT::decode()

Una breve lista de verificación de seguridad#

Fijar el algoritmo es la solución principal. Estos hábitos cierran el resto de las brechas:

  • Nunca aceptes none en producción. No hay razón para que el token de un usuario autenticado no esté firmado.
  • Usa un algoritmo por servicio. Si no necesitas tanto HS256 como RS256, no permitas que tu verificador acepte ambos. Mezclarlos es lo que invita al ataque de confusión.
  • Mantén las claves de verificación tipadas. Carga tu clave pública RSA como un objeto clave, no como una cadena de texto, para que no pueda usarse accidentalmente como secreto HMAC.
  • Valida las reclamaciones, no solo la firma. Verifica exp, iss y aud. Una firma válida en un token destinado a otro servicio sigue siendo un problema.
  • Inspecciona los tokens que recibes. Antes de integrar un token de terceros, decodifícalo y confirma que el encabezado y las reclamaciones coinciden con lo que esperas.

Puedes confirmar todo esto con un token real en segundos. Nuestro decodificador y herramienta de seguridad JWT muestra el encabezado, el payload y qué algoritmo afirma el token, para que puedas detectar un alg: none o un HS256 inesperado antes de que llegue a tu verificador. La guía complementaria sobre cómo leer la salida del decodificador JWT para la seguridad de tokens explica qué te dice cada campo.

Cómo saber si tu aplicación es vulnerable#

No necesitas un equipo de pentest para detectarlo. Tres comprobaciones rápidas cubren la mayoría de los riesgos reales.

Paso 1: ¿Está fijado el algoritmo?#

Busca en tu código cada llamada que verifique un token. Si alguna ruta de verificación omite una lista blanca de algorithms (o su equivalente), esa ruta confía en el encabezado del token y es sospechosa. Esta es la comprobación de mayor valor y toma minutos.

Paso 2: ¿Pasa un token "none"?#

Toma un token válido, cambia su encabezado a {"alg":"none","typ":"JWT"}, modifica un reclamo, elimina la firma (mantén el punto final) y envíalo a un endpoint protegido. Una respuesta 200 con la identidad falsificada confirma la vulnerabilidad. Un 401 confirma que la ruta lo rechaza.

Paso 3: ¿Tu clave pública es realmente pública y algo acepta HS256?#

Si firmas con RS256, asume que la clave pública está en manos de un atacante. Lo único que separa eso de un token falsificado es si algún verificador en tu pila ejecuta HS256. Si la respuesta es sí en algún lugar, estás expuesto al ataque de confusión hasta que fijes RS256.

Preguntas Frecuentes#

¿La vulnerabilidad del algoritmo JWT none sigue siendo relevante en 2026? Sí. Las bibliotecas modernas y mantenidas rechazan alg: none por defecto y requieren una lista blanca explícita, por lo que una instalación nueva suele ser segura. El error persiste en versiones antiguas de bibliotecas, en código JWT hecho a mano y en aplicaciones que anulan los valores predeterminados para "permitir flexibilidad". Auditar tus llamadas de verificación sigue siendo recomendable.

¿Por qué es seguro publicar mi clave pública RS256 si puede falsificar tokens? La clave pública por sí sola es inofensiva. Solo se vuelve peligrosa cuando tu servidor está dispuesto a ejecutar la verificación HS256 y trata esa clave pública como un secreto HMAC. Si corriges la disposición a aceptar HS256 (fijando RS256), publicar la clave pública es tan seguro como el diseño lo pretende.

¿Qué significa "lista blanca de algoritmos" en la práctica? Significa indicarle a tu función de verificación el algoritmo o algoritmos exactos que aceptas, en lugar de dejar que lea el algoritmo del token entrante. En jsonwebtoken es verify(token, key, { algorithms: ["RS256"] }). El verificador ignora entonces el encabezado alg del token al decidir cómo comprobar la firma.

¿Puedo simplemente bloquear la cadena "none" para estar seguro? No. Las listas negras son frágiles. Los atacantes evitan los bloqueos que distinguen mayúsculas y minúsculas con None o NONE, y una lista negra no sirve contra el ataque de confusión RS256 a HS256, que utiliza un valor HS256 perfectamente normal. Una lista blanca de algoritmos aceptados defiende contra ambos ataques a la vez.

¿Cómo puedo inspeccionar qué algoritmo usa un token? Decodifica el primer segmento del token, que es el encabezado codificado en base64url que contiene el campo alg. Puedes hacerlo manualmente o pegar el token en un decodificador JWT que muestre el encabezado, el payload y el algoritmo declarado. La decodificación nunca valida la firma, así que trata el resultado como informativo hasta que tu servidor lo verifique con un algoritmo fijo.

¿Usar un secreto más largo o una clave más fuerte soluciona esto? No. Una clave RSA de 4.096 bits no ayuda si el verificador puede ser engañado para usar modo HMAC, y un secreto HMAC fuerte no ayuda si el servidor acepta tokens none sin firma. Estos ataques evitan la criptografía en lugar de romperla, por lo que la solución es fijar el algoritmo, no aumentar la fortaleza de la clave.

La conclusión sobre la vulnerabilidad del algoritmo JWT None#

La vulnerabilidad del algoritmo JWT None y el ataque de confusión RS256-a-HS256 comparten una misma causa raíz: confiar en la entrada controlada por el atacante para decidir cómo se verifica un token. Eliminar una firma o intercambiar una clave pública como secreto HMAC, y un servidor que lee sus instrucciones del encabezado alg aceptará la falsificación.

Fije el algoritmo con una lista blanca explícita, rechace none en producción y mantenga un algoritmo por servicio. Ese puñado de hábitos elimina toda la clase de errores. Cuando necesite confirmar lo que realmente contiene un token, decodifíquelo primero y verifíquelo después con un algoritmo fijo, y cierre la puerta para siempre.

jwtsecurityvulnerabilityauthentication

More from Molixa

Try Molixa Tools

50+ free AI tools for content creation, SEO, coding, and more. No signup, no watermark.

Explore all tools