
JWT-брутфорсер, написанный на C
Многопоточный взломщик JWT методом полного перебора, написанный на C. Если вам очень повезёт или у вас есть огромные вычислительные мощности, эта программа должна найти секретный ключ JWT токена, позволяя вам подделывать валидные токены. Только для целей тестирования, не ввязывайтесь в неприятности :)
Я использовал реализацию Base64 от Apple, которую слегка изменил.
docker build . -t jwtcrack
docker run -it --rm jwtcrack eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.cAOIAifu3fykvhkHpbuhbvtH807-Z2rI1FS3vX1XMjE
Убедитесь, что у вас установлены заголовочные файлы openssl. В Ubuntu их можно установить с помощью apt-get install libssl-dev
make
Если вы используете Mac, вы можете установить OpenSSL с помощью brew install openssl, но заголовочные файлы будут находиться в другом месте:
make OPENSSL=/usr/local/opt/openssl/include OPENSSL_LIB=-L/usr/local/opt/openssl/lib
$ > ./jwtcrack eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.cAOIAifu3fykvhkHpbuhbvtH807-Z2rI1FS3vX1XMjE
Следующие хеш-функции поддерживаются для HMAC, т.е. для генерации ключевых хешированных кодов аутентификации сообщений: "sha256" для JSON HS256 (HMAC с SHA-256), "sha384" для HS384 и "sha512" для HS512 соответственно. Вы можете указать имя любой другой хеш-функции точно так, как она названа в OpenSSL. Если OpenSSL позволяет использовать эту хеш-функцию для HMAC, то jwtcrack попытается декодировать секрет. Однако, поскольку jwtcrack является только декодером, нет гарантии, что этот алгоритм действительно использовался для кодирования, не говоря уже о том, что он входит в список алгоритмов, разрешённых RFC "JSON Web Algorithms". Смотрите раздел 3.1. RFC 7518 для получения дополнительной информации.
В следующем примере мы используем хеш-функцию sha256, которая соответствует JSON HS256 (HMAC-SHA256), смотрите "sha256" как последний параметр командной строки. Также в этом примере мы указываем максимальную длину секрета в 5 символов и ограничиваем алфавит следующими символами: ABCSNFabcsnf1234
$ > ./jwtcrack eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.cAOIAifu3fykvhkHpbuhbvtH807-Z2rI1FS3vX1XMjE ABCSNFabcsnf1234 5 sha256
В приведённом выше примере ключ — Sn1f, и на среднем ноутбуке 2019 года выпуска (например, с процессором Intel на микроархитектуре Ice Lake) это занимает меньше секунды. Для компиляции программы jwtcrack использовался GCC версии 9.3.0 с флагом "-O3". Она была скомпонована с библиотекой OpenSSL версии 1.1.1f под Linux Ubuntu 20.04.1 LTS.
Здесь, в следующем примере, мы используем "sha512" как последний параметр командной строки для указания HS512 (HMAC-SHA512), а также указываем максимальную длину секрета в 9 символов и ограничиваем алфавит следующими семью строчными латинскими символами: "adimnps".
$ > ./jwtcrack eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJyb2xlIjoiYWRtaW4ifQ.RnWtv7Rjggm8LdMU3yLnz4ejgGAkIxoZwsCMuJlHMwTh7CJODDZWR8sVuNvo2ws25cbH9HWcp2n5WxpIZ9_v0g adimnps 9 sha512
В приведённом выше примере ключ — adminpass, и для его декодирования на ноутбуке с процессором Intel Core i7 1065G7 на микроархитектуре Ice Lake (2019), базовая частота 1.30 ГГц, максимальный турбо 3.90 ГГц) требуется в среднем около 15 секунд. Общее количество процессорных секунд, потреблённых от каждого ядра в пользовательском режиме из-за многопоточности, составляет в среднем около 100 для декодирования этого секрета.
Пример использования "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
Используемая мной реализация base64 (от Apple) иногда содержит ошибки, потому что не все реализации Base64 одинаковы. Поэтому иногда декодирование вашего Base64 токена будет работать лишь частично, и вы сможете найти секрет для вашего токена, который не является правильным.
Если кто-то захочет реализовать более надёжную реализацию Base64, это было бы здорово :)