Распространённые атаки и уязвимости JWT: объяснение

common jwt attacks and vulnerabilities explained

Узнайте о ключевых уязвимостях JWT, таких как подделка токенов, злоупотребление алгоритмом none и обход подписи. Научитесь защищать свои приложения от атак на JWT.

Понимание атак и уязвимостей JSON Web Token (JWT)

JSON Web Token (JWT) стали фундаментальной технологией для безопасной передачи информации между сторонами в формате JSON. Благодаря возможности цифровой подписи и верификации, JWT широко используются для авторизации и аутентификации в современных веб-приложениях. Однако безопасность JWT зависит от точной реализации и настройки. Неправильное использование может привести к серьёзным уязвимостям и рискам эксплуатации.

Строение JSON Web Token

В основе JWT лежат три компонента — заголовок, полезная нагрузка и подпись — каждый из которых закодирован в Base64URL и разделён точками, имея следующую структуру:

HEADER.PAYLOAD.SIGNATURE

Заголовок JWT

Заголовок определяет метаданные токена, включая:

  • alg: криптографический алгоритм для подписи токена (например, HS256, RS256)
  • typ: тип токена, обычно “JWT”

Пример декодированного заголовка:

{
  "alg": "HS256",
  "typ": "JWT"
}

Полезная нагрузка JWT

Полезная нагрузка содержит утверждения (claims), которые представляют собой данные об объекте (обычно пользователе) и дополнительную информацию. Например:

{
  "name": "John Doe",
  "user_name": "john.doe",
  "is_admin": false
}

Утверждения могут быть стандартными (зарегистрированными, например, iss, exp) или настраиваемыми под конкретную логику приложения.

Подпись JWT

Подпись обеспечивает целостность и подлинность токена. Она создаётся путём подписания Base64URL-кодированных заголовка и полезной нагрузки с использованием секрета или приватного ключа, в зависимости от алгоритма:

  1. Закодировать заголовок и полезную нагрузку
  2. Объединить их точкой
  3. Подписать полученную строку указанным алгоритмом (например, HMAC с SHA-256 или RSA)

Например, для алгоритма HS256:

HMACSHA256(
  base64UrlEncode(header) + "." +
  base64UrlEncode(payload),
  secret)

Распространённые уязвимости в реализации JWT

Несмотря на широкое распространение, JWT подвержены ряду уязвимостей, возникающих из-за ошибок конфигурации или реализации. Эти слабые места могут поставить под угрозу безопасность приложений, использующих JWT для аутентификации и авторизации.

1. Пропуск проверки подписи

Многие библиотеки JWT различают декодирование и проверку токена. Функция decode() извлекает содержимое без проверки подписи, тогда как verify() гарантирует правильность подписи. Разработчики, случайно полагающиеся только на decode(), рискуют принять поддельные токены.

Последствия: Злоумышленники могут произвольно изменять токены — повышать права или выдавать себя за других пользователей без обнаружения. Например, изменение утверждения is_admin с false на true в неподписанном токене может предоставить несанкционированный доступ администратора.

2. Разрешение использования алгоритма “None”

Спецификация JWT предусматривает опцию “None” — отсутствие подписи. Если приложение допускает токены с alg: none, злоумышленники могут обойти проверку подписи, полностью удалив её.

Пример из практики: Исторически были успешные атаки, использовавшие принятие alg: none для компрометации сервисов (см. анализ Auth0).

Меры защиты: Явно запрещать алгоритм none и выполнять проверку допустимых алгоритмов по белому списку.

3. Атаки путаницы алгоритмов

JWT поддерживает симметричные (HMAC) и асимметричные (RSA, ECDSA) алгоритмы. Проблемы возникают, когда приложение не проверяет тип алгоритма и позволяет злоумышленнику заменить его (например, RSA на HMAC), обманув проверяющий модуль для использования неподходящего ключа.

Пример: Злоумышленник заменяет alg: RS256 на alg: HS256 и использует публичный ключ как секрет для HMAC, что позволяет подделывать подписи без приватного ключа.

Эта уязвимость отмечена в нескольких библиотеках JWT и остаётся критичной при отсутствии строгой проверки алгоритма.

4. Использование слабых или легко угадываемых секретов для симметричной подписи

В симметричной криптографии (например, HS256) безопасность токена полностью зависит от секретности общего ключа. Слабые секреты, такие как простые пароли или предсказуемые строки, уязвимы к переборам.

Результаты исследований: Анализы показывают, что многие JWT используют слабые секреты, например “123456” или “password” (см. отчёт Snyk по уязвимостям JWT 2023), что облегчает злоумышленникам компрометацию аутентификации.

Рекомендации: Используйте длинные, случайно сгенерированные секреты — желательно более 256 бит — и регулярно обновляйте их.

5. Эксплуатация параметра Key ID (kid)

Параметр kid в заголовке JWT служит для выбора ключа проверки подписи. При отсутствии валидации его можно эксплуатировать разными способами:

  • Инъекции: Зловредный ввод в kid может привести к SQL-инъекциям, удалённому выполнению кода (RCE) или локальному включению файлов (LFI), если применение небезопасно для получения ключей.
  • Обход путём перехода по каталогам: Злоумышленники меняют kid, чтобы ссылаться на произвольные файлы (например, /dev/null) для обхода проверки подписи.
  • SQL-инъекция: Несанкционированные SQL-запросы с пользовательским kid позволяют подменить ключ и подделать подпись.

Совет по безопасности: Очищайте и строго валидируйте параметр kid перед использованием. Применяйте подготовленные выражения для запросов к БД и ограничивайте доступ к файловой системе.

6. Злоупотребление параметром jku

Параметр jku (URL набора JSON Web Key Set) позволяет динамически загружать публичные ключи с удалённого URL. Без должной проверки злоумышленники могут направить приложение на свой JWKS endpoint с поддельными ключами.

  • Атакующий вектор: Изменить jku на злоумышленнический URL, сгенерировать пару ключей и подписывать токены, которые приложение ошибочно примет.
  • Обход защиты: Использование хитростей URL, открытых редиректов, DNS-уловок и SSRF для обхода доменных ограничений или фильтров URL.

Меры снижения риска:

  • Белый список доверенных доменов для значений jku и строгая проверка формата URL.
  • Использование статических или внутренних ключей вместо динамического получения.
  • Реализация надёжных мер защиты от SSRF для предотвращения несанкционированных запросов.

Дополнительные рекомендации и лучшие практики

  • Используйте проверенные библиотеки JWT: Реализуйте JWT с помощью хорошо поддерживаемых библиотек с регулярными обновлениями безопасности.
  • Обеспечьте срок действия токенов: Устанавливайте разумные времена жизни (exp) и строго проверяйте их, чтобы ограничить повторное использование.
  • Проверяйте аудиторию и издателя: Подтверждайте, что токен предназначен для вашего приложения, проверяя утверждения aud и iss.
  • Регулярно обновляйте секреты и ключи: Периодически меняйте криптографические ключи и секреты для минимизации последствий утечек.
  • Применяйте многоуровневую защиту: Верификация JWT должна быть частью комплексной стратегии безопасности с серверными проверками авторизации, ограничением частоты запросов и обнаружением аномалий.

Реальные примеры

Пример 1: Уязвимость путаницы алгоритмов в Auth0
В 2015 году Auth0 раскрыли критическую уязвимость JWT, когда злоумышленник мог обойти аутентификацию, используя путаницу алгоритмов, что подчеркнуло важность проверки алгоритма (источник).

Пример 2: Ошибка настройки JWT в Microsoft Azure Container Service
В 2018 году неправильная валидация JWT в Azure Container Service позволила повысить привилегии, допуская токены с алгоритмом none. Уязвимость была исправлена после сообщения (источник).

Заключение

JSON Web Token являются важным инструментом современной аутентификации и авторизации, но несут значительные риски при неправильной реализации. Злоумышленники используют уязвимости, такие как пропуск проверки подписи, путаница алгоритмов, слабые секреты и небезопасная обработка параметров заголовка JWT, таких как kid и jku. Чтобы защитить приложения, разработчикам необходимо строго следовать лучшим практикам, тщательно валидировать все элементы JWT и использовать надёжные библиотеки.

Регулярные оценки уязвимостей и тестирование безопасности, ориентированное на JWT, жизненно необходимы для поддержания высокой безопасности приложений. Устранение уязвимостей JWT снижает риски несанкционированного доступа, повышения привилегий и масштабных нарушений безопасности.