
Crackeador de fuerza bruta de JWT escrito en C
Un cracker de JWT por fuerza bruta multi-hilo escrito en C. Si tienes mucha suerte o un enorme poder de cómputo, este programa debería encontrar la clave secreta de un token JWT, permitiéndote falsificar tokens válidos. Esto es solo para fines de prueba, no te metas en problemas :)
Utilicé la implementación Base64 de Apple que modifiqué ligeramente.
docker build . -t jwtcrack
docker run -it --rm jwtcrack eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.cAOIAifu3fykvhkHpbuhbvtH807-Z2rI1FS3vX1XMjE
Asegúrate de tener instalados los encabezados de openssl.
En Ubuntu puedes instalarlos con apt-get install libssl-dev
make
Si usas una Mac, puedes instalar OpenSSL con brew install openssl, pero los encabezados se almacenarán en una ubicación diferente:
make OPENSSL=/usr/local/opt/openssl/include OPENSSL_LIB=-L/usr/local/opt/openssl/lib
$ > ./jwtcrack eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.cAOIAifu3fykvhkHpbuhbvtH807-Z2rI1FS3vX1XMjE
Las siguientes funciones hash son compatibles con HMAC, es decir, para generar códigos de autenticación de mensajes con clave hash: "sha256" para JSON HS256 (HMAC usando SHA-256), "sha384" para HS384 y "sha512" para HS512, respectivamente. Puedes especificar el nombre de cualquier otra función hash exactamente como se llama en OpenSSL. Si OpenSSL permite que esta función hash se use para HMAC, entonces jwtcrack intentará descifrar el secreto. Sin embargo, dado que jwtcrack es solo un decodificador, no hay garantía de que este algoritmo se haya utilizado realmente para la codificación, y mucho menos entre la lista de algoritmos permitidos en el RFC "JSON Web Algorithms". Consulta la sección 3.1. del RFC 7518 para más detalles.
En el siguiente ejemplo, usamos una función hash sha256 que corresponde a JSON HS256 (HMAC-SHA256), observa "sha256" como último parámetro de línea de comandos. Además, en este ejemplo especificamos una longitud máxima de secreto de 5 caracteres, y limitamos el alfabeto a los siguientes caracteres: ABCSNFabcsnf1234
$ > ./jwtcrack eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.cAOIAifu3fykvhkHpbuhbvtH807-Z2rI1FS3vX1XMjE ABCSNFabcsnf1234 5 sha256
En el ejemplo anterior, la clave es Sn1f, y toma menos de un segundo en un portátil promedio fabricado alrededor de 2019 (por ejemplo, con una CPU Intel basada en la microarquitectura Ice Lake). Se utilizó GCC versión 9.3.0 con "-O3" para compilar el programa jwtcrack. Se enlazó con la biblioteca OpenSSL versión 1.1.1f en Linux Ubuntu 20.04.1 LTS.
Aquí, en el siguiente ejemplo, usamos "sha512" como último parámetro de línea de comandos para especificar HS512 (HMAC-SHA512), también especificamos una longitud máxima de secreto de 9 caracteres, y limitamos el alfabeto a los siguientes siete caracteres latinos en minúscula: "adimnps".
$ > ./jwtcrack eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJyb2xlIjoiYWRtaW4ifQ.RnWtv7Rjggm8LdMU3yLnz4ejgGAkIxoZwsCMuJlHMwTh7CJODDZWR8sVuNvo2ws25cbH9HWcp2n5WxpIZ9_v0g adimnps 9 sha512
En el ejemplo anterior, la clave es adminpass, y toma alrededor de 15 segundos en promedio para descifrar en un portátil con CPU Intel Core i7 1065G7 en microarquitectura Ice Lake (2019), frecuencia base 1.30 GHz, turbo máximo 3.90 GHz). El número combinado de segundos de CPU consumidos de cada uno de los núcleos en modo usuario debido al multi-hilo es de aproximadamente 100 en promedio para descifrar ese secreto.
Ejemplo de uso de "sha384":
$ > ./jwtcrack eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzM4NCJ9.eyJyb2xlIjoiYWRtaW4ifQ.31xCH3k8VRqB8l5qBy7RyqI2htyCskBy_4cIWpk3o43UkIMW-IcjTUEL_NyFXUWJ 0123456789 6 sha384
/usr/bin/time -f "Total number of CPU-seconds consumed directly from each of the CPU cores: %U\nElapsed real wall clock time used by the process: %E" ./jwtcrack eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJyb2xlIjoiYWRtaW4ifQ.RnWtv7Rjggm8LdMU3yLnz4ejgGAkIxoZwsCMuJlHMwTh7CJODDZWR8sVuNvo2ws25cbH9HWcp2n5WxpIZ9_v0g adimnps 9 sha512
La implementación Base64 que uso (de Apple) a veces tiene errores porque no todas las implementaciones de Base64 son iguales. Por lo tanto, a veces, el descifrado de tu token Base64 solo funcionará parcialmente y, en consecuencia, podrás encontrar un secreto para tu token que no es el correcto.
Si alguien está dispuesto a implementar una implementación Base64 más robusta, sería genial :)