¿Qué es, Ataque JWT?

En esta sección, veremos cómo los problemas de diseño y el manejo defectuoso de los tokens web JSON (JWT) pueden hacer que los sitios web sean vulnerables a una variedad de ataques de alta gravedad. Dado que los JWT se utilizan con mayor frecuencia en la autenticación, la gestión de sesiones y los mecanismos de control de acceso, estas vulnerabilidades pueden comprometer potencialmente todo el sitio web y sus usuarios.

No se preocupe si no está familiarizado con los JWT y cómo funcionan; cubriremos todos los detalles relevantes a medida que avanzamos. También proporcionamos una serie de laboratorios deliberadamente vulnerables para que pueda practicar la explotación de estas vulnerabilidades de forma segura contra objetivos realistas.

¿Qué son los JWT?

Los tokens web JSON (JWT) son un formato estandarizado para enviar datos JSON firmados criptográficamente entre sistemas. En teoría, pueden contener cualquier tipo de datos, pero se usan más comúnmente para enviar información («reclamaciones») sobre los usuarios como parte de los mecanismos de autenticación, manejo de sesiones y control de acceso.

A diferencia de los tokens de sesión clásicos, todos los datos que necesita un servidor se almacenan en el lado del cliente dentro del propio JWT. Esto hace que los JWT sean una opción popular para sitios web altamente distribuidos donde los usuarios necesitan interactuar sin problemas con múltiples servidores back-end.

Solicita una cotización del mejor escaner de vulnerabilidades de sitios web y aplicativos expuestos, con precios por anualidad e intercambio de targets, BURP SUITE ENTERPRISE es el único que lo ofrece, cambia YA!

Cotizar..

Formato JWT

Un JWT consta de 3 partes: un encabezado, una carga útil y una firma. Cada uno de ellos está separado por un punto, como se muestra en el siguiente ejemplo:

eyJraWQiOiI5MTM2ZGRiMy1jYjBhLTRhMTktYTA3ZS1lYWRmNWE0NGM4YjUiLCJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJwb3J0c3dpZ2dlciIsImV4cCI6MTY0ODAzNzE2NCwibmFtZSI6IkNhcmxvcyBNb250b3lhIiwic3ViIjoiY2FybG9zIiwicm9sZSI6ImJsb2dfYXV0aG9yIiwiZW1haWwiOiJjYXJsb3NAY2FybG9zLW1vbnRveWEubmV0IiwiaWF0IjoxNTE2MjM5MDIyfQ.SYZBPIBg2CRjXAJ8vCER0LA_ENjII1JakvNQoP-Hw6GG1zfl4JyngsZReIfqRvIAEi5L4HV0q7_9qGhQZvy9ZdxEJbwTxRs_6Lb-fZTDpW6lKYNdMyjw45_alSCZ1fypsMWz_2mTpQzil0lOtps5Ei_z7mM7M8gCwe_AGpI53JxduQOaB5HkT5gVrv9cKu9CsW5MS6ZbqYXpGyOG5ehoxqm8DL5tFYaW3lB50ELxi0KsuTKEbD0t5BCl0aCR2MBJWAbN-xeLwEenaqBiwPVvKixYleeDQiBEIylFdNNIMviKRgXiYuAvMziVPbwSgkZVHeEdF5MQP1Oe2Spac-6IfA

Las partes de encabezado y carga útil de un JWT son solo objetos JSON codificados en base64url. El encabezado contiene metadatos sobre el token en sí, mientras que la carga contiene las «reclamaciones» reales sobre el usuario. Por ejemplo, puede decodificar la carga útil del token anterior para revelar las siguientes afirmaciones:

{
"iss": "portswigger",
"exp": 1648037164,
"name": "Carlos Montoya",
"sub": "carlos",
"role": "blog_author",
"email": "carlos@carlos-montoya.net",
"iat": 1516239022
}

En la mayoría de los casos, cualquier persona con acceso al token puede leer o modificar fácilmente estos datos. Por lo tanto, la seguridad de cualquier mecanismo basado en JWT depende en gran medida de la firma criptográfica.

Firma JWT

El servidor que emite el token generalmente genera la firma mediante el hash del encabezado y la carga útil. En algunos casos, también cifran el hash resultante. De cualquier manera, este proceso implica una clave secreta. Sin conocer este secreto, no es posible generar una firma válida para un encabezado y una carga útil determinados. Cualquier cambio en el encabezado o la carga útil significaría que la firma ya no coincide. Esto proporciona una forma para que los servidores verifiquen que ninguno de los datos ha sido manipulado desde que se emitió el token porque

JWT contra JWS contra JWE

La especificación JWT es en realidad muy limitada. Solo define un formato para representar información («reclamaciones») como un objeto JSON que se puede transferir entre dos partes. En la práctica, los JWT no se usan realmente como una entidad independiente. La especificación JWT se amplía con las especificaciones JSON Web Signature (JWS) y JSON Web Encryption (JWE), que definen formas concretas de implementar JWT.

¿Qué son los ataques JWT?

Los ataques JWT involucran a un usuario que envía JWT modificados al servidor para lograr un objetivo malicioso. Por lo general, este objetivo es eludir la autenticación y los controles de acceso haciéndose pasar por otro usuario que ya se ha autenticado.

¿Cuál es el impacto de los ataques JWT?

El impacto de los ataques JWT suele ser grave. Si un atacante puede crear sus propios tokens válidos con valores arbitrarios, puede escalar sus propios privilegios o hacerse pasar por otros usuarios, tomando el control total de sus cuentas.

Solicita una cotización del mejor escaner de vulnerabilidades de sitios web y aplicativos expuestos, con precios por anualidad e intercambio de targets, BURP SUITE ENTERPRISE es el único que lo ofrece, cambia YA!

Cotizar..

¿Cómo surgen las vulnerabilidades a los ataques JWT?

Las vulnerabilidades de JWT suelen surgir debido a un manejo defectuoso de JWT dentro de la propia aplicación. Las diversas especificaciones relacionadas con los JWT tienen un diseño relativamente flexible, lo que permite a los desarrolladores de sitios web decidir muchos detalles de implementación por sí mismos. Esto puede resultar en que introduzcan vulnerabilidades accidentalmente incluso cuando se usan bibliotecas reforzadas.

Estas fallas de implementación generalmente significan que la firma del JWT no se verifica correctamente. Esto permite que un atacante manipule los valores pasados ​​a la aplicación a través de la carga útil del token. Incluso si la firma se verifica sólidamente, si realmente se puede confiar en ella depende en gran medida de que la clave secreta del servidor permanezca en secreto. Si esta clave se filtra de alguna manera, o se puede adivinar o utilizar la fuerza bruta, un atacante puede generar una firma válida para cualquier token arbitrario, comprometiendo todo el mecanismo.

Cómo trabajar con JWT en Burp Suite

En caso de que no haya trabajado con JWT en el pasado, le recomendamos que se familiarice con las características relevantes de Burp Suite antes de intentar los laboratorios de este tema.

Explotación de verificación de firma JWT defectuosa

Por diseño, los servidores no suelen almacenar ninguna información sobre los JWT que emiten. En cambio, cada token es una entidad completamente autónoma. Esto tiene varias ventajas, pero también presenta un problema fundamental: el servidor en realidad no sabe nada sobre el contenido original del token, ni siquiera cuál era la firma original. Por lo tanto, si el servidor no verifica la firma correctamente, no hay nada que impida que un atacante realice cambios arbitrarios en el resto del token.

Por ejemplo, considere un JWT que contenga las siguientes afirmaciones:

{ "username": "carlos", "isAdmin": false }

Si el servidor identifica la sesión en función de este username, la modificación de su valor podría permitir que un atacante se haga pasar por otros usuarios que iniciaron sesión. De manera similar, si el isAdminvalor se usa para el control de acceso, esto podría proporcionar un vector simple para la escalada de privilegios.

En los primeros dos laboratorios, verá algunos ejemplos de cómo podrían verse estas vulnerabilidades en aplicaciones del mundo real.

Aceptar firmas arbitrarias

Las bibliotecas JWT suelen proporcionar un método para verificar tokens y otro que simplemente los decodifica. Por ejemplo, la biblioteca Node.js jsonwebtokentiene verify()decode().

Ocasionalmente, los desarrolladores confunden estos dos métodos y solo pasan tokens entrantes al decode()método. Esto significa efectivamente que la aplicación no verifica la firma en absoluto.

Aceptar tokens sin firma

Entre otras cosas, el encabezado JWT contiene un alg parámetro. Esto le dice al servidor qué algoritmo se usó para firmar el token y, por lo tanto, qué algoritmo debe usar al verificar la firma.

{ "alg": "HS256", "typ": "JWT" }

Esto es inherentemente defectuoso porque el servidor no tiene otra opción que confiar implícitamente en la entrada controlable por el usuario del token que, en este punto, no se ha verificado en absoluto. En otras palabras, un atacante puede influir directamente en cómo el servidor verifica si el token es confiable.

Los JWT se pueden firmar utilizando una variedad de algoritmos diferentes, pero también se pueden dejar sin firmar. En este caso, el algparámetro se establece en none, lo que indica un denominado «JWT no seguro». Debido a los peligros obvios de esto, los servidores generalmente rechazan tokens sin firma. Sin embargo, como este tipo de filtrado se basa en el análisis de cadenas, a veces puede omitir estos filtros utilizando técnicas clásicas de ofuscación, como mayúsculas y codificaciones inesperadas.

Solicita una cotización del mejor escaner de vulnerabilidades de sitios web y aplicativos expuestos, con precios por anualidad e intercambio de targets, BURP SUITE ENTERPRISE es el único que lo ofrece, cambia YA!

Cotizar..

Claves secretas de fuerza bruta

Algunos algoritmos de firma, como HS256 (HMAC + SHA-256), utilizan una cadena independiente arbitraria como clave secreta. Al igual que una contraseña, es crucial que un atacante no pueda adivinar fácilmente este secreto o forzarlo por la fuerza bruta. De lo contrario, es posible que puedan crear JWT con cualquier encabezado y valores de carga útil que deseen, y luego usar la clave para volver a firmar el token con una firma válida.

Al implementar aplicaciones JWT, los desarrolladores a veces cometen errores como olvidarse de cambiar los secretos predeterminados o de marcador de posición. Incluso pueden copiar y pegar fragmentos de código que encuentran en línea y luego olvidarse de cambiar un secreto codificado que se proporciona como ejemplo. En este caso, puede ser trivial para un atacante aplicar fuerza bruta al secreto de un servidor utilizando una lista de palabras de secretos conocidos .

Claves secretas de fuerza bruta usando hashcat

Recomendamos usar hashcat para aplicar fuerza bruta a las claves secretas. Puede instalar hashcat manualmente , pero también viene preinstalado y listo para usar en Kali Linux.

Solo necesita un JWT válido y firmado del servidor de destino y una lista de palabras de secretos conocidos . Luego puede ejecutar el siguiente comando, pasando el JWT y la lista de palabras como argumentos:

hashcat -a 0 -m 16500 <jwt> <wordlist>

Hashcat firma el encabezado y la carga útil del JWT usando cada secreto en la lista de palabras, luego compara la firma resultante con la original del servidor. Si alguna de las firmas coincide, hashcat genera el secreto identificado en el siguiente formato, junto con varios otros detalles:

<jwt>:<identified-secret>

Como hashcat se ejecuta localmente en su máquina y no depende del envío de solicitudes al servidor, este proceso es extremadamente rápido, incluso cuando se usa una lista de palabras enorme.

Una vez que haya identificado la clave secreta, puede usarla para generar una firma válida para cualquier encabezado JWT y carga útil que desee. Para obtener detalles sobre cómo volver a firmar un JWT modificado en Burp Suite, consulte Firma de JWT .

Si el servidor usa un secreto extremadamente débil, incluso puede ser posible aplicar fuerza bruta a este carácter por carácter en lugar de usar una lista de palabras.

Inyecciones de parámetros de encabezado JWT

De acuerdo con la especificación JWS, solo el algparámetro del encabezado es obligatorio. Sin embargo, en la práctica, los encabezados JWT (también conocidos como encabezados JOSE) a menudo contienen otros parámetros. Los siguientes son de particular interés para los atacantes.

  • jwk(JSON Web Key): proporciona un objeto JSON incrustado que representa la clave.

  • jku(URL del conjunto de claves web JSON): proporciona una URL desde la cual los servidores pueden obtener un conjunto de claves que contienen la clave correcta.

  • kid(ID de clave): proporciona una ID que los servidores pueden usar para identificar la clave correcta en los casos en que hay varias claves para elegir. Según el formato de la clave, esta puede tener un kidparámetro coincidente.

Como puede ver, cada uno de estos parámetros controlables por el usuario le dice al servidor del destinatario qué clave usar al verificar la firma. En esta sección, aprenderá cómo explotarlos para inyectar JWT modificados firmados con su propia clave arbitraria en lugar del secreto del servidor.

Inyectar JWT autofirmados a través del parámetro jwk

La especificación JSON Web Signature (JWS) describe un jwk parámetro de encabezado opcional, que los servidores pueden usar para incrustar su clave pública directamente dentro del token en formato JWK.

JWK

Un JWK (JSON Web Key) es un formato estandarizado para representar claves como un objeto JSON.

Puede ver un ejemplo de esto en el siguiente encabezado JWT:

{
"kid": "ed2Nf8sb-sD6ng0-scs5390g-fFD8sfxG",
"typ": "JWT",
"alg": "RS256",
"jwk": {
"kty": "RSA",
"e": "AQAB",
"kid": "ed2Nf8sb-sD6ng0-scs5390g-fFD8sfxG",
"n": "yy1wpYmffgXBxhAUJzHHocCuJolwDqql75ZWuCQ_cb33K2vh9m"
}

}

Idealmente, los servidores solo deberían usar una lista blanca limitada de claves públicas para verificar las firmas JWT. Sin embargo, los servidores mal configurados a veces usan cualquier clave que esté incrustada en el jwkparámetro.

Puede aprovechar este comportamiento firmando un JWT modificado con su propia clave privada RSA y luego incrustando la clave pública correspondiente en el jwkencabezado.

Aunque puede agregar o modificar manualmente el jwkparámetro en Burp, la extensión JWT Editor proporciona una función útil para ayudarlo a probar esta vulnerabilidad:

  1. Con la extensión cargada, en la barra de pestañas principal de Burp, vaya a la pestaña Teclas del editor JWT .

  2. Genere una nueva clave RSA.

  3. Envíe una solicitud que contenga un JWT a Burp Repeater.

  4. En el editor de mensajes, cambie a la pestaña Token web JSON generado por la extensión y modifique la carga útil del token como desee.

  5. Haga clic en Ataque , luego seleccione Embedded JWK . Cuando se le solicite, seleccione su clave RSA recién generada.

  6. Envíe la solicitud para probar cómo responde el servidor.

También puede realizar este ataque manualmente agregando el jwkencabezado usted mismo. Sin embargo, es posible que también deba actualizar el kidparámetro de encabezado de JWT para que coincida con el kidde la clave incrustada. El ataque incorporado de la extensión se encarga de este paso por usted.

Inyectar JWT autofirmados a través del parámetro jku

En lugar de incrustar claves públicas directamente usando el jwkparámetro de encabezado, algunos servidores le permiten usar el jkuparámetro de encabezado (JWK Set URL) para hacer referencia a un JWK Set que contiene la clave. Al verificar la firma, el servidor obtiene la clave relevante de esta URL.

{
"keys": [
{
"kty": "RSA",
"e": "AQAB",
"kid": "75d0ef47-af89-47a9-9061-7c02a610d5ab",
"n": "o-yy1wpYmffgXBxhAUJzHHocCuJolwDqql75ZWuCQ_cb33K2vh9mk6GPM9gNN4Y_qTVX67WhsN3JvaFYw-fhvsWQ"
},
{
"kty": "RSA",
"e": "AQAB",
"kid": "d8fDFo-fS9-faS14a9-ASf99sa-7c1Ad5abA",
"n": "fc3f-yy1wpYmffgXBxhAUJzHql79gNNQ_cb33HocCuJolwDqmk6GPM4Y_qTVX67WhsN3JvaFYw-dfg6DH-asAScw"
}
]
}

Los conjuntos de JWK como este a veces se exponen públicamente a través de un punto final estándar, como /.well-known/jwks.json.

Los sitios web más seguros solo obtendrán claves de dominios confiables, pero a veces puede aprovechar las discrepancias de análisis de URL para evitar este tipo de filtrado. Cubrimos algunos ejemplos de estos en nuestro tema sobre SSRF .

Inyectar JWT autofirmados a través del parámetro kid

Los servidores pueden usar varias claves criptográficas para firmar diferentes tipos de datos, no solo JWT. Por esta razón, el encabezado de un JWT puede contener un kidparámetro (ID de clave), que ayuda al servidor a identificar qué clave usar al verificar la firma.

Las claves de verificación a menudo se almacenan como un conjunto JWK. En este caso, el servidor puede simplemente buscar el JWK con lo mismo kidque el token. Sin embargo, la especificación JWS no define una estructura concreta para este ID, es solo una cadena arbitraria a elección del desarrollador. Por ejemplo, podrían usar el kidparámetro para apuntar a una entrada particular en una base de datos, o incluso al nombre de un archivo.

Si este parámetro también es vulnerable al cruce de directorios , un atacante podría obligar al servidor a utilizar un archivo arbitrario de su sistema de archivos como clave de verificación.

{ "kid": "../../path/to/file", "typ": "JWT", "alg": "HS256", "k": "asGsADas3421-dfh9DGN-AFDFDbasfd8-anfjkvc" }

Esto es especialmente peligroso si el servidor también admite JWT firmados mediante un algoritmo simétrico . En este caso, un atacante podría potencialmente apuntar el kidparámetro a un archivo estático predecible, luego firmar el JWT usando un secreto que coincida con el contenido de este archivo.

En teoría, podría hacer esto con cualquier archivo, pero uno de los métodos más simples es usar /dev/null, que está presente en la mayoría de los sistemas Linux. Como se trata de un archivo vacío, recuperarlo devuelve nulo. Por lo tanto, firmar el token con un byte nulo codificado en Base64 dará como resultado una firma válida.

Si el servidor almacena sus claves de verificación en una base de datos, el kidparámetro del encabezado también es un vector potencial para ataques de inyección SQL .

Otros parámetros de encabezado JWT interesantes

Los siguientes parámetros de encabezado también pueden ser interesantes para los atacantes:

  • cty(Tipo de contenido): a veces se usa para declarar un tipo de medio para el contenido en la carga útil de JWT. Esto generalmente se omite del encabezado, pero la biblioteca de análisis subyacente puede admitirlo de todos modos. Si ha encontrado una manera de omitir la verificación de firma, puede intentar inyectar un ctyencabezado para cambiar el tipo de contenido a text/xmlapplication/x-java-serialized-object, lo que potencialmente puede habilitar nuevos vectores para XXE y ataques de deserialización .

  • x5c(Cadena de certificados X.509): a veces se utiliza para pasar el certificado de clave pública X.509 o la cadena de certificados de la clave utilizada para firmar digitalmente el JWT. Este parámetro de encabezado se puede usar para inyectar certificados autofirmados, de forma similar a los ataques de jwkinyección de encabezado que se analizaron anteriormente. Debido a la complejidad del formato X.509 y sus extensiones, el análisis de estos certificados también puede generar vulnerabilidades. Los detalles de estos ataques están más allá del alcance de estos materiales, pero para obtener más detalles, consulte CVE-2017-2800 y CVE-2018-2633 .

Confusión del algoritmo JWT

Incluso si un servidor usa secretos sólidos que usted no puede usar por fuerza bruta, aún puede falsificar JWT válidos firmando el token usando un algoritmo que los desarrolladores no han anticipado. Esto se conoce como un ataque de confusión de algoritmos.

Cómo prevenir ataques JWT

Puede proteger sus propios sitios web contra muchos de los ataques que hemos cubierto tomando las siguientes medidas de alto nivel:

  • Utilice una biblioteca actualizada para manejar JWT y asegúrese de que sus desarrolladores entiendan completamente cómo funciona, junto con las implicaciones de seguridad. Las bibliotecas modernas hacen que sea más difícil implementarlas de forma insegura sin darse cuenta, pero esto no es infalible debido a la flexibilidad inherente de las especificaciones relacionadas.

  • Asegúrese de realizar una verificación de firma sólida en cualquier JWT que reciba y tenga en cuenta los casos extremos, como los JWT firmados con algoritmos inesperados.

  • Aplique una lista blanca estricta de hosts permitidos para el jku encabezado.

  • Asegúrese de no ser vulnerable al recorrido de ruta o inyección de SQL a través del kidparámetro de encabezado.

Mejores prácticas adicionales para el manejo de JWT

Aunque no es estrictamente necesario para evitar la introducción de vulnerabilidades, recomendamos seguir las siguientes prácticas recomendadas al usar JWT en sus aplicaciones:

  • Establezca siempre una fecha de vencimiento para cualquier token que emita.

  • Evite enviar tokens en parámetros de URL siempre que sea posible.

  • Incluya el aud reclamo (audiencia) (o similar) para especificar el destinatario previsto del token. Esto evita que se utilice en diferentes sitios web.

  • Permita que el servidor emisor revoque tokens (al cerrar la sesión, por ejemplo).

Si te ha gustado, ¡compártelo con tus amigos!

Scroll al inicio

Portal de Clientes