Содержание:
- Что такое JWT?
- Заголовок
- Полезная нагрузка
- Подпись
- Что такое SECRET_KEY?
- Атаки на JWT:
- Базовые атаки:
- Нет алгоритма
- Изменяем алгоритм с RS256 на HS256
- Без проверки подписи
- Взлом секретного ключа
- Использование произвольных файлов для проверки
- Продвинутые атаки:
- SQL-инъекция
- Параметр поддельного заголовка
- Внедрение заголовка ответа HTTP
- Прочие уязвимости
- Базовые атаки:
Что такое JSON Web Token?
Веб-токен JSON обычно используется для авторизации в клиент-серверных приложениях. JWT состоит из трех элементов:
- Заголовок
- Полезная нагрузка
- Подпись
Заголовок
Это объект JSON, который представляет собой метаданные токена. Чаще всего состоит из двух полей:
- Тип токена
- Алгоритм хэширования
Официальный сайт предлагает два алгоритма хэширования:
- «HS256»
- «RS256»
Но на самом деле любой алгоритм с приватным ключом может быть использован.
Полезная нагрузка
Это также объект JSON, который используется для хранения такой информации о пользователе, как:
- идентификатор
- имя пользователя
- роль
- время генерации токена и т.д.
Подпись
Это наиболее важная часть, поскольку она определяет целостность токена путем подписания заголовка и полезной нагрузки в кодировке Base64-URL, разделенных точкой (.) с секретным ключом. Например, чтобы сгенерировать токен с помощью алгоритма HS256, псевдокод будет таким:
// Use Base64-URL algorithm for encoding and concatenate with a dotdata = (base64urlEncode(header) + '.' + base64urlEncode(payload))// Use HS256 algorithm with "SECRET_KEY" string as a secretsignature = HMACSHA256(data , SECRET_KEY)// Complete token
JWT = data + "." + base64UrlEncode(signature)
Что такое SECRET_KEY?
Как правило, JWT может быть сгенерирован с помощью двух механизмов шифрования, таких как:
- Симметричное
- Ассиметричное
Симметричное шифрование:
Этот механизм требует единственного ключа для создания и проверки JWT.
Например, пользователь "Vasya" сгенерировал JWT с «h1dd1n_m1ss1g3» в качестве секретного ключа. Любой человек, знающий этот ключ, может с его помощью изменить токен. JWT при этом останется действительным.
Самый распространенный алгоритм для этого типа — HS256.
Асимметричное шифрование:
Этот механизм требует открытого ключа для проверки и закрытого ключа для подписи.
Например, если "Vasya" использовал это шифрование, то он единственный, кто может создать новый токен, используя закрытый ключ, тогда как "Petya" может только проверить токен с помощью открытого ключа, но не может его изменить.
Наиболее распространенный алгоритм для этого типа — RS256.
Атаки на JWT
Чтобы подделать токен, необходимо иметь правильные ключи (например, секретный ключ для HS256, открытый и закрытый ключи для RS256), но если конфигурация JWT не реализована правильно, то есть много способов обойти элементы управления, которые позволяют изменить токен и получить несанкционированный доступ.
Базовые атаки
Для выполнения всех этих атак нам понадобиться JWT_Tool
1. Нет алгоритма
Если приложению не удается проверить значение заголовка «alg», то мы можем изменить его значение на «none», и таким образом оно исключает необходимость действительной подписи для проверки. Например:
// Modified Header of JWT after changing the "alg" parameter{
"alg": "none",
"typ": "JWT"
}
Команда:
python3 jwt_tool.py <JWT> -X a
Здесь jwt_tool создал различные полезные нагрузки для использования этой уязвимости и обхода всех ограничений, пропустив раздел «Подпись».
2. Изменяем алгоритм с RS256 на HS256
Как было сказано выше, алгоритму RS256 нужен закрытый ключ для подделки данных и соответствующий открытый ключ для проверки подлинности подписи. Но если мы сможем изменить алгоритм подписи с RS256 на HS256, мы заставим приложение использовать только один ключ для выполнения обеих задач, что является нормальным поведением алгоритма HMAC.
Таким образом рабочий процесс будет преобразован из асимметричного в симметричное шифрование. Теперь мы можем подписывать новые токены тем же открытым ключом.
Команда:
python3 jwt_tool.py <JWT> -S hs256 -k public.pem
В данном случае мы сначала загружаем открытый ключ (public.pem) из приложения, а затем подписываем токен с помощью алгоритма HS256, используя этот ключ. Таким образом, мы можем создавать новые токены и вставлять полезную нагрузку в любое существующее утверждение.
3. Без проверки подписи
Иногда при фаззинге данных в разделе заголовка и полезной нагрузки приложение не возвращает ошибку. Это значит, что подпись не проверяется после того, как она была подписана сервером авторизации. Таким образом, мы можем вставить любую полезную нагрузку в заявку, а токен всегда будет действительным.
Команда:
python3 jwt_tool.py <JWT> -I -pc name -pv admin
Здесь часть подписи не проверяется, а значит можно смягчить утверждение «имени» в разделе полезной нагрузки, сделав себя «администратором».
4. Взлом секретного ключа
Мы можем получить доступ к файлу SECRET_KEY с помощью уязвимостей, таких как
- LFI
- XXE
- SSRF
Если это невозможно, то все равно можно провести другие атаки, чтобы проверить, использует ли токен какую-либо слабую секретную строку для шифрования.
Для этой цели можно использовать расширение BurpSuite под названием JWT Heartbreaker.
Такое раскрытие поставит под угрозу весь механизм безопасности, поскольку теперь мы можем генерировать произвольные токены с секретным ключом.
Но чтобы убедиться, что полученная нами строка является действительным ключом SECRET_KEY или нет? Мы можем использовать функцию Crack в jwt_tool.
Команда:
python3 jwt_tool.py <JWT> -C -d secrets.txt
// Use -p flag for a string
5. Использование произвольных файлов для проверки
Key ID (kid) – это необязательный заголовок, имеющий строковый тип, который используется для обозначения конкретного ключа, присутствующего в файловой системе или базе данных, а затем использования его содержимого для проверки подписи. Этот параметр полезен, если приложение имеет несколько ключей для подписи токенов, но может быть опасным, если он является инъекционным, поскольку в этом случае злоумышленник может указать на конкретный файл, содержимое которого предсказуемо.
Например, «/dev/null» называется нулевым файлом устройства и всегда ничего не возвращает, поэтому он отлично работает в системах на основе Unix.
Команда:
python3 jwt_tool.py <JWT> -I -hc kid -hv "../../dev/null" -S hs256 -p ""
В качестве альтернативы можно использовать любой файл, присутствующий в корневом веб-каталоге, например, CSS или JS. Также можно использовать его содержимое для проверки подписи.
Другое решение проблемы:
python3 jwt_tool.py -I -hc kid -hv "путь / к / файлу" -S hs256 -p "Содержимое файла"
Продвинутые атаки:
1. SQL-инъекция
Эта уязвимость может возникнуть, если любой параметр, который извлекает какое-либо значение из базы данных, не очищается должным образом. Благодаря чему можно решать CTF задачи.
Например, если приложение использует алгоритм RS256, но открытый ключ виден в заявлении «pk» в разделе Payload, тогда можно преобразовать алгоритм подписи в HS256 и создавать новые токены.
Команда для подсчета количества столбцов:
python3 jwt_tool.py <JWT> -I -pc name -pv "imparable' ORDER BY 1--" -S hs256 -k public.pem// Increment the value by 1 until an error will occur
2. Параметр поддельного заголовка
JSON Web Key Set (JWKS) — это набор открытых ключей, которые используются для проверки токена. Вот пример:
Этот файл хранится на доверенном сервере, приложение может указывать на этот файл через параметры заголовка:
- «jku»
- «x5u»
Но мы можем управлять URL-адресом с помощью таких уловок, как:
- открытый редирект
- добавление символа @ после имени хоста и т. д.
Затем мы можем перенаправить Приложение на наш вредоносный сервер вместо доверенного сервера и генерировать новые токены, так как мы контролируем как открытые, так и закрытые ключи.
JSON Set URL (jku):
Этот параметр указывает на набор открытых ключей в формате JSON (атрибуты n и e в JWKS), а «jwt_tool» автоматически создает файл JWKS с именем «jwttool_custom_jwks.json» для этой атаки при первом запуске инструмента после установки.
Команда:
python3 jwt_tool.py <JWT> -X s -ju "https://attacker.com/jwttool_custom_jwks.json"
X.509 URL (x5u):
Этот параметр указывает на сертификат открытого ключа X.509 или цепочку сертификатов (атрибут x5c в JWKS). Вы можете сгенерировать этот сертификат с соответствующим закрытым ключом следующим образом:
openssl req -newkey rsa:2048 -nodes -keyout private.pem -x509 -days 365 -out attacker.crt -subj "/C=AU/L=Brisbane/O=CompanyName/CN=pentester"
Здесь с использованием OpenSSL сертификат был создан в «attacker.crt», который теперь может быть встроен в файл JWKS с атрибутом «x5c», а его эксплуатация может осуществляться следующим образом:
python3 jwt_tool.py <JWT> -S rs256 -pr private.pem -I -hc x5u -hv "https://attacker.com/custom_x5u.json"
Встроенные открытые ключи:
Если сервер встраивает открытые ключи непосредственно в токен с помощью параметров «jwk» (JSON Web Key) или «x5c» (цепочка сертификатов X.509), попробуйте заменить их своими собственными открытыми ключами и подписать токен соответствующим закрытым ключом.
3. Внедрение заголовка ответа HTTP
Предположим, что если приложение ограничивает любой управляемый URL-адрес в параметрах «jku» или «x5c», тогда мы можем использовать уязвимость внедрения заголовка ответа, чтобы добавить встроенный JWKS в ответ HTTP и заставить приложение использовать это для проверки подписи.
4. Прочие уязвимости
Веб-токены JSON – это еще одна форма пользовательского ввода, все параметры в которой должны быть очищены должным образом, иначе это может привести к уязвимостям, таким как:
- LFI
- RCE и другим.
Но это не означает, что приложение по-прежнему безопасно, ведь, если злоумышленник не может подделать JWT, он попытается украсть их с помощью неправильной конфигурации:
- XSS
- CSRF
- CORS и т. д.
Удачных пентестов!
lair
alg
— это не алгоритм хэширования. Это вообще криптографический алгоритм (RFC 7515). И они будут отличаться в зависимости от того, JWS у ваc, или JWE.Нет никакого "официального сайта". Есть RFC 7519 (с обновлениями).
Что такое "алгоритм хэширования с приватным ключом"? Правильно, нет такой вещи. Смотри первый пункт в этом комментарии. И нет, в
alg
может быть не любой алгоритм: JWS, JWE.… и дальше хорошо видно, что вы путаете шифрование с подписанием.
Что такое "конфигурация JWT"? На стороне издателя или на стороне проверяющего?
(но вообще, конечно, приведенные атаки — это наглядная иллюстрация того, почему не надо делать свою собственную безопасность на основе JWT, а надо брать готовые решения, желательно стандартизованные)
sshikov
> приведенные атаки
А вы можете объяснить, каким боком тут вообще SQL-инъекция?
P.S. Мне кажется, что это вообще-то перевод: medium.com/bugbountywriteup/attacking-json-web-tokens-jwts-d1d51a1e17cb
lair
Приблизительно при этом: "Веб-токены JSON – это еще одна форма пользовательского ввода". Грубо говоря, если кто-то от большого ума взял значение из пришедшего токена, и запихнул его в SQL-запрос (например, чтобы найти издателя по пришедшему идентификатору) без соответствующей обработки, то можно получить SQL-инъекцию.
Это, понятное дело, атака не на токен, а с помощью токена. И она предполагает, что выполнилось множество предусловий.
sshikov
Так я именно об этом. Это имеет к токену точно такое же отношение, как к… ну в общем, притянуто за уши.
Ну и да, если взглянуть на оригинал, то большая часть проблем — они оттуда.
lair
Полностью согласен.
А какая разница, откуда? Все равно в итоге тут написана чушь.
sshikov
Для нас — никакой. А вот автор, раз не поставил значок «перевод» — отвечает за ошибки сам. По-идее.
mayorovp
Даже если поставил — всё равно отвечает, ибо нефиг переводить чушь.
sshikov
Ну в общем да. Но все-таки, в случае перевода можно приписать что-то типа: «Во, смотрите какую неоднозначную чушь пишут на медиуме» :)
lair
О, ваше гугль-фу лучше моего. Я смог найти только вот это: https://www.slideshare.net/OWASP_Poland/opd-2019-attacking-jwt-tokens
Нехорошо, да.