Cabecera Penligente

json web signature decode: Guía del Ingeniero de Seguridad para no ser poseído

El control de acceso moderno vive y muere sobre tokens basados en JSON. Cuando inspeccionas un token de acceso de OAuth, un token de ID de OpenID Connect o una sesión de API firmada, normalmente estás viendo un token JSON. Firma web JSON (JWS) estructura. Los motores de búsqueda enviarán a mucha gente a herramientas de "descodificación de firmas web json" que parecen convertir mágicamente cadenas opacas en JSON legible.

Para los ingenieros de seguridad ofensiva y defensiva, ése es sólo el primer paso. Descifrar un JWS te dice lo que el token reclamacionesPero no le dice si esas afirmaciones son fiables, si la firma se aplica correctamente o si la implementación ya está en una base de datos CVE.

Este artículo explica lo que ocurre realmente cuando se realiza la decodificación de firmas web json, cómo las vulnerabilidades del mundo real surgieron de errores sutiles en torno a la verificación de JWS, y cómo construir un flujo de trabajo repetible que se ajuste a una canalización de pentest automatizada y aumentada por IA.

Dominio de la descodificación de firmas web JSON: Análisis Avanzado, Exploits CVE y Defensa AI Penligent
json web signature decode: Guía del Ingeniero de Seguridad para no ser poseído

Qué es realmente una firma web JSON

Según la especificación JWS, una firma web JSON representa contenido arbitrario protegido por una firma digital o una MAC, utilizando estructuras basadas en JSON. Proporciona integridad y autenticidad para una secuencia de bytes, independientemente de lo que esos bytes representen. (IETF Datatracker)

En la práctica, la mayoría de las veces esa secuencia de bytes es un objeto JSON de reclamaciones - que es lo que llamamos un JSON Web Token (JWT). JWS en sí está definido en [RFC 7515], mientras que JWT está en un estándar hermano centrado en cómo se estructuran e interpretan esas declaraciones. (Medio)

La forma compacta familiar tiene este aspecto:

eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.
eyJzdWIiOiIxMjM0Iiwic2NvcGUiOlsicmVhZCIsIndyaXRlIl0sImV4cCI6MTczNDkxMjAwMH0.
ODU5Y...firma-bytes-here...

Conceptualmente, son tres partes codificadas en Base64URL unidas por puntos:

PiezaNombreDescripción
1ª parteCabeceraJSON que describe el algoritmo, pistas clave (chico, jwk, x5u), tipo de ficha
2ª parteCarga útilReclamaciones: asunto, ámbitos, emisor, caducidad, etc.
3ª parteFirmaSalida de la firma base64url(header) + "." + base64url(payload)

Una operación de decodificación de firma web json, ya sea realizada por una herramienta en línea o en sus propios scripts, sólo invierte la codificación Base64URL de las dos primeras partes e imprime el JSON. Lo que hace no probar que la firma es válida a menos que la herramienta realice explícitamente la verificación con una clave conocida y un conjunto de algoritmos restringido. (desarrollador.pingidentidad.com)

Cómo funcionan realmente las herramientas de descodificación de firmas web json

La mayoría de los descodificadores JWT / JWS - como las herramientas de desarrollo comunes utilizadas en los navegadores o en los playgrounds basados en web - implementan el mismo pipeline mínimo:

  1. Dividir los puntos en tres segmentos.
  2. Base64URL-decodifica los dos primeros segmentos.
  3. Analícelos como JSON para la cabecera y la carga útil.
  4. Si se suministra una clave de verificación, se vuelve a calcular la firma utilizando el algoritmo anunciado en la cabecera y se compara con el tercer segmento. (desarrollador.pingidentidad.com)

Desde la perspectiva de un ingeniero de seguridad, los pasos 1 a 3 son suficientemente seguros para un análisis offline; el paso 4 es donde se esconden la mayoría de las vulnerabilidades.

Fragmento mínimo de descodificación en Python

A continuación se muestra un fragmento deliberadamente simple de decodificación en Python, útil cuando se busca entre los tokens capturados durante un pentest:

importar base64
importar json

def b64url_decode(datos: str) -> bytes:
    # JWT padding handling
    padding = '=' * (-len(data) % 4)
    return base64.urlsafe_b64decode(datos + relleno)

def decode_jws(token: str):
    header_b64, payload_b64, signature_b64 = token.split('.')
    cabecera = json.loads(b64url_decode(cabecera_b64))
    payload = json.loads(b64url_decode(payload_b64))
    return cabecera, carga, firma_b64

jws = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...."
h, p, sig = decode_jws(jws)
print("Cabecera:", h)
print("Carga útil:", p)

Tenga en cuenta que esta función nunca llama a una rutina de verificación; sólo está decodificando. A menudo, eso es exactamente lo que quieres cuando evalúas un nuevo objetivo: una inspección rápida sin suposiciones criptográficas.

Fragmento de Node.js con verificación

Una vez que se pasa de la descodificación a la verificación, cada detalle es importante:

import jwt de "jsonwebtoken";
import fs from "fs";

const publicKey = fs.readFileSync("public.pem", "utf-8");

function verifyJws(token) {
  // Crítico: bloquear explícitamente los algoritmos soportados
  return jwt.verify(token, publicKey, {
    algoritmos: ["RS256"],
  });
}

Si omite el algoritmos lista blanca y dejar que la biblioteca infiera el algoritmo de la cabecera no confiable, estás reproduciendo exactamente las condiciones que llevaron a múltiples CVEs JWT.

La descodificación es inofensiva, confiar en los datos descodificados no es

Un patrón aparece una y otra vez en los informes de incidentes y CVE: los desarrolladores tratan descodificado datos JWT / JWS como si ya estuvieran verificado. Múltiples escritos modernos sobre temas de seguridad JWT enfatizan que la decodificación Base64URL es trivial y que el secreto de un token no proviene de "ser difícil de leer". (PortSwigger)

Destacan tres clases recurrentes de fallos:

  1. El campo "alg" se trata como una fuente de verdad. Si tu código de verificación extrae el algoritmo a utilizar de la cabecera - que es controlada por el usuario - estás invitando a ataques de confusión de algoritmos.
  2. En ninguno se acepta accidentalmente. El estándar JWT históricamente requería soporte para "ninguno" como un algoritmo que significa "sin protección de integridad". El análisis clásico de Auth0 mostró cómo varias bibliotecas respetaron ingenuamente esta elección, permitiendo que los tokens sin firmar pasaran las comprobaciones. (Auth0)
  3. Sugerencias clave (chicoincrustado jwk, x5u) no se validan. Tanto la RFC del JWS como las guías de pruebas destacan que permitir que el token elija su propia clave de verificación sin una lista blanca estricta permite a los atacantes introducir claves públicas arbitrarias o forzar la búsqueda de claves en lugares controlados por los atacantes. (PortSwigger)

En otras palabras, la descodificación de firmas web json te da observabilidad. No te da confianza. Esa distinción es lo que separa una configuración de depuración segura de un encabezado de ejecución remota de código.

Cuando la descodificación se encuentra con los CVE: modos concretos de fallo del JWS

Para comprender lo mal que pueden ir las cosas cuando se confunden la descodificación y la verificación, merece la pena echar un vistazo a algunas CVE que giran en torno a la lógica de verificación del JWS.

CVE-2015-9235 - Confusión de clave HS/RS en jsonwebtoken

En Node.js jsonwebtoken antes de la versión 4.2.2, un error de diseño permitía eludir la verificación de firmas cambiando de un algoritmo asimétrico (familias RS256 / ES256) a uno simétrico (HS256). La ruta de código vulnerable reutilizaba el mismo valor -la clave pública RSA- como secreto HMAC cuando el atacante cambiaba el alg a HS256. (nvd.nist.gov)

Desde el punto de vista del atacante, el flujo de trabajo es sencillo:

  1. Decodifica el token original e inspecciona la cabecera.
  2. Extraer la clave pública del servidor (por ejemplo, de un endpoint JWK o de un certificado).
  3. Falsificar un nuevo token con una cabecera HS256, utilizando la clave pública como secreto HMAC.
  4. Presentar el token falsificado; el servidor lo trata erróneamente como válido.

En este caso, la descodificación proporcionaba al atacante la materia prima (cabecera, algoritmo, ubicaciones de las claves); la lógica de verificación hacía el resto.

CVE-2018-1000531 - aceptar el ninguno algoritmo

Esta vulnerabilidad rastreaba casos en los que las bibliotecas aceptaban tokens firmados con la extensión ninguno tratándolos como válidos a pesar de carecer de firma. El patrón de explotación es casi cómicamente simple: cambiar "alg": "RS256" a "alg": "none"elimine la parte de la firma y compruebe si la API de destino acepta el token. (0xn3va.gitbook.io)

CVE-2023-48238 - confusión de algoritmos en json-web-token

En json-web-token para JavaScript fue vulnerable a otro ataque de confusión de algoritmos. El problema principal: el algoritmo utilizado para la verificación se tomaba directamente de la cabecera del token, que en ese momento no era de confianza. Esto permitía a los atacantes elegir un algoritmo más conveniente que el que el operador del servidor pensaba que estaba aplicando. (nvd.nist.gov)

CVE-2024-54150 - confusión en una implementación de JWT en C

Más recientemente, el cjwt C sufría un fallo crítico de confusión de algoritmos, ahora rastreado como CVE-2024-54150. Una revisión del código reveló que la implementación no distinguía correctamente los algoritmos basados en HMAC de los basados en RSA / EC al verificar los tokens, abriendo de nuevo la puerta a la confusión de claves. (nvd.nist.gov)

Estos casos no son curiosidades históricas; demuestran que, incluso en 2023-2024, los errores sutiles en la ruta de verificación del JWS siguen siendo una fuente activa de vulnerabilidades graves.

Para no perderlos de vista durante una evaluación, muchos equipos crean una chuleta como la siguiente:

CVECausa principalTema de ataqueLección principal
2015-9235HS vs RS confusión claveAlgoritmo de confusiónAplicar la lista blanca de algoritmos; claves separadas por algoritmo
2018-1000531ninguno aceptada como firmaFirma nulaNunca permita ninguno en producción
2023-48238Algoritmo de JWT no fiableAlgoritmo de confusiónIgnorar cabecera algutilizar sólo la configuración del servidor
2024-54150Sin distinción HS vs RS/ECAlgoritmo de confusión (C)Tratar MAC vs firma como caminos fundamentalmente diferentes

Durante un ejercicio de decodificación de firmas web json, mapear explícitamente los tokens observados contra esta tabla es una forma rápida de detectar qué playbooks deberías probar.

Un flujo de trabajo práctico de decodificación para pentesters

Cuando se evalúa una API o un sistema SSO que se basa en JWS, un flujo de trabajo disciplinado que priorice la descodificación evita tanto los puntos ciegos como las conjeturas ruidosas.

  1. Capturar y catalogar fichas. Utilice su proxy o arnés de pruebas para capturar todos los tokens: Cabeceras de autorización, cookies, parámetros de URL. Agrúpalos por emisor y público.
  2. Descodificación de la cabecera y la carga útil sin conexión. Utilice secuencias de comandos como el fragmento de Python anterior o jwt_tool sólo para descodificar; nunca confíe en un servicio en línea para fichas sensibles en compromisos reales. (GitHub)
  3. Construir una matriz de cabecera. Para cada familia de fichas, registre alg, chicopresencia de jku / jwk / x5uy cualquier campo de cabecera personalizado. Aquí es donde la guía de PortSwigger sobre JWKs incrustadas y claves proporcionadas por atacantes se vuelve directamente procesable. (PortSwigger)
  4. Inferir patrones de gestión de claves. Basándose en los campos de cabecera y los puntos finales conocidos (/.well-known/jwks.json), esboza cómo se distribuyen y rotan las llaves.
  5. Pruebe las clases conocidas de errores.
    • Prueba con firma nula / ninguno si la biblioteca o pila históricamente las ha soportado.
    • Realizar intentos de confusión de claves HS/RS donde los algs no estén bloqueados.
    • Sonda chico para atravesar directorios o incluir archivos.
    • Intentar la inyección JWK embebida donde la especificación lo permite pero la implementación puede no restringirlo.
  6. Entonces, y sólo entonces, pase a los intentos de explotación total. En esta fase, debe saber con precisión lo que intenta demostrar, en lugar de limitarse a lanzar cargas útiles a una caja negra.

En este proceso, la decodificación de firmas web json es la capa de observabilidad para el resto de su metodología de ataque.

Integración de la descodificación de firmas web json en un proceso de pentest basado en IA (Penligent.ai)

El análisis manual funciona para un único compromiso; a gran escala, los equipos necesitan algo más parecido a un pipeline. Una plataforma asistida por IA como Penligent.ai puede integrar la descodificación de firmas web json directamente en sus fases de reconocimiento y explotación.

En una configuración típica, la plataforma recibe el tráfico HTTP de un navegador aislado o un proxy, extrae automáticamente los tokens candidatos y realiza una descodificación JWS masiva de las cabeceras y las cargas útiles. A continuación, el agente de inteligencia artificial agrupa los tokens por emisor, algoritmo y pistas clave, buscando anomalías como una diversidad de algoritmos inesperada, extrañas chico codificaciones o combinaciones inusuales de reivindicaciones.

Una vez que se construye esa línea de base, el motor de ataque de Penligent puede ejecutar automáticamente libros de jugadas JWT / JWS curados: intentos de firma nula, escenarios de confusión de algoritmos, JWK incrustado o jku y sondas conocidas inspiradas en CVE. En lugar de dejar estas comprobaciones en manos de la memoria humana, el sistema las trata como casos de prueba repetibles que se ejecutan en cada objetivo y devuelven los resultados a una lista de riesgos basada en pruebas y a un informe legible por máquina.

Para los ingenieros de seguridad que están creando una capacidad interna de "equipo rojo de IA", el cableado de la descodificación de firmas web json en una canalización automatizada de este tipo suele ser una de las piezas de fontanería de bajo nivel que más se aprovechan.

Lista de comprobación y lecturas complementarias

Si su trabajo diario implica la emisión o verificación de tokens JWS / JWT, puede tratar esto como un listón mínimo:

  • Aplicar una lista estricta de algoritmos permitidos en el servidor; no leer nunca alg de un token no fiable como política.
  • Separe las claves entre las firmas asimétricas y los secretos HMAC; nunca reutilice una clave pública RSA como clave HMAC.
  • Desactivar permanentemente ninguno en las bibliotecas de producción y rechazar cualquier token que lo anuncie.
  • Tratar todos los campos de cabecera (chico, jku, jwk, x5u) como entradas no fiables y validarlas con un conjunto de claves fijas o una lista blanca.
  • Mantenga sus bibliotecas JWT parcheadas; revise periódicamente CVEs como CVE-2015-9235, CVE-2018-1000531, CVE-2023-48238 y CVE-2024-54150 para ver si su pila está afectada. (Laboratorio de Swissky)
  • Añade pruebas de regresión que ejerciten explícitamente escenarios de no/algoritmo-confusión.

Para profundizar más, merece la pena marcar estas referencias en inglés y enlazarlas desde sus runbooks internos:

  • El núcleo [JSON Web Signature (JWS) RFC 7515] del IETF. (IETF Datatracker)
  • Sección de OWASP sobre [Testing JSON Web Tokens] en la Guía de Pruebas de Seguridad Web. (Fundación OWASP)
  • Laboratorios de la Academia de Seguridad Web de PortSwigger sobre [ataques JWT] y [confusión de algoritmos]. (PortSwigger)
  • El clásico artículo de Tim McLean sobre Auth0 [vulnerabilidades críticas en las bibliotecas de tokens web JSON]. (Auth0)
  • El borrador en evolución [JWT Best Current Practices] en el grupo de trabajo OAuth del IETF. (IETF)

Usada correctamente, la decodificación de firmas web json no es sólo una comodidad de depuración; es la puerta de entrada a una forma sistemática de entender, atacar y endurecer el tejido de autenticación de tus aplicaciones.

Comparte el post:
Entradas relacionadas