Источник: https://github.com/AnaktaCTF/CTF/blob/main — WEB/JWT_testing.md
JSON Web Tokens (JWT) — это популярный стандарт для передачи данных между клиентом и сервером, часто используемый для аутентификации и авторизации в веб-приложениях. В соревнованиях Capture The Flag (CTF) задачи с JWT встречаются регулярно, особенно в категории Web, и требуют от участников понимания их структуры, уязвимостей и способов эксплуатации. В этой статье мы разберем, что такое JWT, почему они важны, какие проблемы безопасности с ними связаны, как их взламывать в контексте CTF и какие инструменты помогут в этом процессе.
Что такое JWT и для чего они нужны?
JWT — это компактный токен, состоящий из трех частей, разделенных точками (.):
- Header (заголовок): содержит метаданные, такие как тип токена (
typ: "JWT") и алгоритм подписи (alg). - Payload (полезная нагрузка): хранит данные, например, идентификатор пользователя (
sub), время выпуска (iat) или срок действия (exp). - Signature (подпись): криптографическая подпись для проверки целостности токена.
Каждая часть закодирована в Base64URL и выглядит так:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
Назначение в веб-приложениях:
JWT часто используется вместо сессий на сервере. После аутентификации сервер выдает токен клиенту, который затем отправляет его с каждым запросом в заголовке Authorization: Bearer <token>. Сервер проверяет подпись и доверяет данным в токене, не обращаясь к базе данных.
В CTF:
JWT обычно появляется в задачах как часть механизма аутентификации. Цель — подделать токен, обойти ограничения или получить доступ к привилегированным ресурсам (например, админ-панели).
Безопасность JWT: где кроются уязвимости?
Хотя JWT выглядит надежно благодаря криптографической подписи, ошибки в реализации делают его уязвимым. Вот ключевые проблемы, которые часто эксплуатируются в CTF:
-
Слабый секрет подписи
- Если токен подписан симметричным алгоритмом (например, HS256), сервер использует секретный ключ. Слабый или предсказуемый ключ (например,
password123) позволяет подделать токен. - В CTF: разработчики могут случайно использовать известные строки или ключи из исходного кода.
- Если токен подписан симметричным алгоритмом (например, HS256), сервер использует секретный ключ. Слабый или предсказуемый ключ (например,
-
Алгоритм "none"
- Некоторые реализации JWT допускают указание
alg: "none", отключая проверку подписи. Если сервер это принимает, токен становится полностью доверенным без защиты. - В CTF: частая уязвимость в старых или плохо настроенных системах.
- Некоторые реализации JWT допускают указание
-
Неправильная обработка алгоритмов
- Сервер может не проверять, совпадает ли алгоритм в заголовке с ожидаемым. Это позволяет переключить HS256 (симметричный) на RS256 (асимметричный) и использовать публичный ключ для подписи.
- В CTF: публичный ключ иногда доступен в
/jwt.pemили других открытых файлах.
-
Утечка данных в Payload
- Payload не шифруется, а лишь кодируется в Base64. Если в нем хранятся чувствительные данные (пароли, роли), их можно просто декодировать.
- В CTF: флаг может быть спрятан прямо в токене.
-
Недостаточная валидация claims
- Сервер может не проверять поля вроде
exp(срок действия) илиsub(идентификатор), что позволяет подменить их значения. - В CTF: изменение
subна ID админа часто дает доступ к флагу.
- Сервер может не проверять поля вроде
Техники взлома JWT в CTF
Теперь перейдем к практическим методам эксплуатации, которые помогут вам решить задачу с JWT в соревновании.
1. Декодирование и анализ токена
Первый шаг — понять, что внутри. Используйте онлайн-декодеры (например, jwt.io) или Python:
import base64
import json
token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjMiLCJyb2xlIjoiZ3Vlc3QifQ.abcd1234"
header, payload, signature = token.split(".")
print(json.loads(base64.urlsafe_b64decode(header + "==")))
print(json.loads(base64.urlsafe_b64decode(payload + "==")))
- Проверьте
algв заголовке и данные в payload (например,role,sub). - В CTF флаг иногда лежит прямо в payload, например,
{ "flag": "ctf{token_leak}" }.
2. Атака на слабый секрет (HS256)
Если токен использует HS256, подпись — это HMAC-SHA256 от header.payload с секретным ключом. Попробуйте угадать ключ:
- Источники: исходный код,
.env,/config, стандартные строки вродеsecretили123456. - Инструмент:
jwt-crackerили скрипт:
import hmac
import hashlib
def check_jwt(secret, token):
header, payload, signature = token.split(".")
expected = base64.urlsafe_b64encode(
hmac.new(secret.encode(), f"{header}.{payload}".encode(), hashlib.sha256).digest()
).decode().rstrip("=")
return expected == signature
token = "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJhZG1pbiJ9.abcd1234"
with open("wordlist.txt", "r") as f:
for secret in f:
if check_jwt(secret.strip(), token):
print(f"Found secret: {secret}")
break
- В CTF: создайте новый токен с
role: "admin"и этим ключом.
3. Использование "none" алгоритма
Поменяйте alg на none и удалите подпись:
- Оригинал:
eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJhZG1pbiJ9.abcd1234 - Новый:
eyJhbGciOiJub25lIn0.eyJzdWIiOiJhZG1pbiJ9. - В CTF: отправьте токен серверу. Если он принимает, вы в деле.
4. Переключение на RS256
Если сервер не проверяет алгоритм, замените HS256 на RS256 и подпишите токен приватным ключом:
- Найдите публичный ключ (
.pemфайл или через/jwt/publickey). - Сгенерируйте пару ключей (
openssl genrsa,openssl rsa) и подпишите:
echo -n "eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJhZG1pbiJ9" | openssl dgst -sha256 -sign private.pem | base64
- В CTF: сервер проверит подпись публичным ключом и примет токен.
5. Подмена claims
Измените payload, например, sub: "guest" → sub: "admin", и пересчитайте подпись (если ключ известен). Используйте jwt.io или Python-скрипт для генерации.
- В CTF: проверьте, как сервер реагирует на разные роли или ID.
Инструменты для взлома JWT
Для эффективной работы с JWT в CTF полезно иметь под рукой специализированные инструменты. Вот подборка самых популярных и их применение:
-
jwt.io
- Что это: Онлайн-сервис для декодирования, создания и проверки JWT.
- Применение: Быстро раскодируйте токен, чтобы увидеть header и payload. Если у вас есть секрет, сгенерируйте новый токен с измененными данными (например,
role: "admin"). - В CTF: Идеально для быстрого старта и тестирования "none" или подмены claims.
-
Burp Suite
- Что это: Инструмент для перехвата и модификации HTTP-запросов.
- Применение: Перехватывайте запросы с JWT в заголовке
Authorization, меняйте токен на поддельный и отправляйте серверу. Плагин "JWT Editor" упрощает анализ и редактирование. - В CTF: Незаменим для задач, где нужно протестировать сервер на уязвимости вроде "none" или слабой валидации.
-
jwt-cracker
- Что это: Утилита для brute-force секрета в HS256-токенах.
- Применение: Установите через npm (
npm install -g jwt-cracker) и запустите:jwt-cracker "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJhZG1pbiJ9.abcd1234" wordlist.txt - В CTF: Используйте с хорошим wordlist’ом (например, rockyou.txt), если секрет слабый.
-
hashcat
- Что это: Мощный инструмент для взлома хэшей, включая HMAC-SHA256 в JWT.
- Применение: Преобразуйте токен в формат hashcat (
header.payload:signature) и атакуйте:hashcat -m 16500 -a 0 token.txt wordlist.txt - В CTF: Подходит для задач с длинными или сложными секретами, где нужна скорость GPU.
-
Python с библиотеками (PyJWT)
- Что это: Библиотека для работы с JWT (
pip install pyjwt). - Применение: Декодируйте, создавайте и проверяйте токены:
import jwt token = "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJhZG1pbiJ9.abcd1234" secret = "password" decoded = jwt.decode(token, secret, algorithms=["HS256"]) new_token = jwt.encode({"sub": "admin"}, secret, algorithm="HS256") print(new_token) - В CTF: Гибкость для кастомных атак, например, подмена алгоритма или автоматизация.
- Что это: Библиотека для работы с JWT (
-
OpenSSL
- Что это: Утилита для работы с криптографией, полезна для RS256.
- Применение: Подпишите токен приватным ключом:
echo -n "header.payload" | openssl dgst -sha256 -sign private.pem | base64 - В CTF: Незаменимо для задач с переключением на асимметричные алгоритмы.
Практический пример из CTF
Задача: Вы получили токен eyJhbGciOiJIUzI1NiJ9.eyJ1c2VyIjoiZ3Vlc3QiLCJpYXQiOjE2NTAwMDB9.dummy и доступ к странице /profile. На /admin вас не пускают.
- Декодируем в jwt.io:
{"alg": "HS256"}и{"user": "guest", "iat": 1650000}. - Пробуем слабые ключи с jwt-cracker: в
/configна сервере лежитsecret = "password". - Генерируем новый токен с
user: "admin"в PyJWT или jwt.io. - Отправляем через Burp Suite в
/admin— получаем флаг:ctf{jwt_cracked}.
Советы для CTF
- Всегда проверяйте доступные файлы (
/robots.txt,/debug) — там могут быть ключи или подсказки. - Используйте Burp Suite для перехвата и модификации токенов в запросах.
- Автоматизируйте brute-force секретов с помощью
jwt-crackerилиhashcat. - Время — ваш враг: начинайте с простых атак вроде "none" или декодирования.
JWT — это мощный инструмент, но его неправильная реализация открывает двери для атак. В CTF такие задачи учат разбираться в криптографии, внимательности к деталям и умению эксплуатировать ошибки разработчиков. Вооружитесь инструментами, практикуйтесь на платформах вроде Hack The Box или CTFtime — и скоро ни один токен не устоит перед вами!
Теперь статья полностью охватывает тему с инструментами. Если нужно что-то еще добавить (например, больше примеров или деталей про конкретный инструмент), дайте знать!