
Cracker de força bruta para JWT escrito em C
Um quebrador de JWT multi-threaded escrito em C. Se você tiver muita sorte ou um enorme poder computacional, este programa deve encontrar a chave secreta de um token JWT, permitindo que você forje tokens válidos. Isso é apenas para fins de teste, não se coloque em apuros :)
Usei a implementação Apple Base64 que modifiquei ligeiramente.
docker build . -t jwtcrack
docker run -it --rm jwtcrack eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.cAOIAifu3fykvhkHpbuhbvtH807-Z2rI1FS3vX1XMjE
Certifique-se de ter os headers do openssl instalados.
No Ubuntu você pode instalá-los com apt-get install libssl-dev
make
Se você usa um Mac, pode instalar o OpenSSL com brew install openssl, mas os headers serão armazenados em um local diferente:
make OPENSSL=/usr/local/opt/openssl/include OPENSSL_LIB=-L/usr/local/opt/openssl/lib
$ > ./jwtcrack eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.cAOIAifu3fykvhkHpbuhbvtH807-Z2rI1FS3vX1XMjE
As seguintes funções hash são suportadas para HMAC, ou seja, para gerar códigos de autenticação de mensagens com chave hash: "sha256" para JSON HS256 (HMAC usando SHA-256), "sha384" para HS384 e "sha512" para HS512, respectivamente. Você pode especificar o nome de qualquer outra função hash exatamente como ela é nomeada no OpenSSL. Se o OpenSSL permitir que esta função hash seja usada para HMAC, então jwtcrack tentará decodificar o segredo. No entanto, como jwtcrack é apenas um decodificador, não há garantia de que este algoritmo foi realmente usado para codificação, muito menos entre a lista de algoritmos permitidos para o RFC "JSON Web Algorithms". Veja a seção 3.1. do RFC 7518 para mais detalhes.
No exemplo a seguir, usamos uma função hash sha256 que corresponde a JSON HS256 (HMAC-SHA256), veja o "sha256" como último parâmetro da linha de comando. Além disso, neste exemplo especificamos o comprimento máximo do segredo de 5 caracteres e limitamos o alfabeto aos seguintes caracteres: ABCSNFabcsnf1234
$ > ./jwtcrack eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.cAOIAifu3fykvhkHpbuhbvtH807-Z2rI1FS3vX1XMjE ABCSNFabcsnf1234 5 sha256
No exemplo acima, a chave é Sn1f, e leva menos de um segundo em um notebook médio fabricado por volta de 2019 (por exemplo, com uma CPU Intel baseada na microarquitetura Ice Lake). A versão GCC 9.3.0 com "-O3" foi usada para compilar o programa jwtcrack. Ele foi vinculado com a biblioteca OpenSSL versão 1.1.1f no Linux Ubuntu 20.04.1 LTS.
Aqui, no próximo exemplo, usamos "sha512" como último parâmetro da linha de comando para especificar HS512 (HMAC-SHA512), também especificamos o comprimento máximo do segredo de 9 caracteres e limitamos o alfabeto aos seguintes sete caracteres latinos minúsculos: "adimnps".
$ > ./jwtcrack eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJyb2xlIjoiYWRtaW4ifQ.RnWtv7Rjggm8LdMU3yLnz4ejgGAkIxoZwsCMuJlHMwTh7CJODDZWR8sVuNvo2ws25cbH9HWcp2n5WxpIZ9_v0g adimnps 9 sha512
No exemplo acima, a chave é adminpass, e leva cerca de 15 segundos em média para decodificar em um notebook com CPU Intel Core i7 1065G7 na microarquitetura Ice Lake (2019), frequência base 1.30 GHz, turbo máximo 3.90 GHz). O número combinado de segundos de CPU consumidos de cada um dos núcleos no modo de usuário devido ao multithreading é de cerca de 100 em média para decodificar esse segredo.
Exemplo 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
A implementação base64 que uso (da Apple) às vezes é problemática porque nem toda implementação Base64 é igual. Então, às vezes, a descriptografia do seu token Base64 funcionará apenas parcialmente e, assim, você conseguirá encontrar um segredo para seu token que não é o correto.
Se alguém estiver disposto a implementar uma implementação Base64 mais robusta, isso seria ótimo :)