JWT-Атаки
E1texОбщие понятия, концепция JWT
Привет, Гайз, разбавим немного серию статей про повышение привилегий в ОС Линукс другой тематикой. Сегодня с Вами разберем достаточно известный тип атак на клиентскую часть приложения - JWT-атаки.

Прочитайте статью до конца и только после этого приступайте к практике. В конце полезная инфа, которая чуточку облегчит Вам жизнь.
JWT(JSON Web Token) - это открытый стандарт создания токенов, основанный на формате JSON(формат {key}: {value}).
JWT используется в:
1. Аутентификациях.
2. Системном управлении.
3. Контроле доступа.
Формат JWT состоит из хидеров, пэйлоада и подписи, которая генерируется из хидеров и пэйлоада. Хидер и пойлоад части - это просто JSON-объекты закодированные в Base-64. Пример JWT-токена:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
Декодируем из Base-64:
{
"alg": "HS256",
"typ": "JWT"
}
{
"sub": "1234567890",
"name": "John Doe",
"iat": 1516239022
}
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
256-bit secret key)
JWT подпись
Что касается подписи, она формируется путем хэширования хидера и пэйлоада, т.е., если JWT настроена правильно, без закрытого ключа изменить хидеры мы не сможем. Чтобы лучше понять, как работает JWT, перейдите на офф. сайт jwt.io, там можно самому генерить токены.
JWS, JWE
Когда люди говорят о JWT-токенах, часто имеется ввиду JWS(JSON Web Signature) или JWE(JSON Web Encryption). Сам по себе JWT выполняет только одну задачу - десереализацию JSON-объектов. Именно поэтому существуют JWS и JWE, они дополняют JWT.
JWT Burp Extensions
Перейдем к практике, для подмены JWT-токенов обычно используется одно расширение - JWT Editor, на практике я использовал его в паре с другим расширением под названием JSON Web Tokens, с помощью него можно достаточно просто расшифровывать JWT, используя найденный хэш ключ, но к этому вернемся чуть позже. Расширения, как всегда, ставим в Extender -> BApp Store
Виды JWT-Атак
Здесь с Вами разберем самые распространенные атаки, безусловно их на самом деле больше, но остальные приколы JWT, по типу интересных хидеров, я упомяну косвенно, а то статья превратится во что-то неприлично долгое.
Для начала, чтобы не повторяться, все последующие атаки будут начинаться со следующих шагов:
1)Авторизируемся на сайте, переходим в HTTP History. Находим GET-запрос, содержащий JWT-токен и оправляем его в Repeater.

2)В Repeater переходим во вкладку JSON Web Token для изменения нашего токена.

3)Меняем параметр sub на логин от аккунта, в который хотим зайти.

При детальном рассмотрении атак и дополнении этапов, они будут нумероваться начиная с этапа №4.
Байпас аутентификации через неавторизованную подпись
Если взглянуть на известные библиотеки, которые работают с JWT, они обычно предоставляют нам два метода - verify(), который отвечает за верификацию подписи, и decode(), который отвечает за декодировку токена. Если разработчики упустили этот момент, может быть такое, что будет использоваться только метод decode(), все будет работать, но это позволит злоумышленнику легко менять любые данные, которые ему захочется.
Сам пример такой атаки и состоит в трех первых шагах, т.е. после изменения параметра "sub", мы уже получим доступ в аккаунт жертвы:
4) Если взглянуть на Response, мы можем увидеть, что мы залогинились под аккаунтом администратора.

Токен без подписи
В JWT есть обязательный хидер "alg". Он нужен для того, чтобы сервер понимал, какой алгоритм хеширования был использован для хэширования подписи. Однако, если заменить значение на none, а часть с подписью удалить, сервер поймет, что это небезопасный токен без подписи. Обычно сервера не пропускают такие запросы, но бывают исключения. Рассмотрим на примере:
4) Удаляем все, что идет после второй точки, т.е. старую подпись (точку оставляем!)

5) Меняем параметр "alg" на "none", что означает, что подписи у нашего токена не будет.

6) Отправляем наш запрос и видим, что мы залогинились под аккаунтом администратора.

Все вышеперечисленные действия с модификацией "alg" и подписью могут быть выполнены автоматически с помощью кнопки "none" Signing Algorithm во вкладке расширения

Брутфорс ключа по словарю
Здесь все предельно просто, нам понадобится hashcat для эксплуатации этой уязвимости. Может случится такое, что разработчики, например, забыли заменить стандартный ключ. Есть много вордлистов с такими ключами. С помощью таких вордлистов можно попробовать побрутить ключ JWT подписи.
(ссылка на гит с листом уже в нашем чате: https://t.me/E7CHAT/3369)
4) Создаем .txt файл и копируем туда наш JWT-токен.
Для того, чтобы выйти с сохранением из vim редактора, нажимаем esc и вписываем :wq, что означает write and quit.

5) Скачиваем с гитхаба наш вордлист с JWT ключами.
6) Запускаем hashcat с параметрами "-a 0"(Attack Mode: Straight) и "-m 16500"(ID хэша с hashcat wiki), после параметров вписываем сначала файл с JWT-токеном, потом вордлист.



7) Переходим во вкладку JWT Editors Keys и создаем там новый симметричный ключ в JWK формате, ключу "k" присваиваем значение нашего ключа, который мы получили в hashcat, в кодировке Base64.


8) Нажимаем на кнопку sign вкладки Repeater>JSON Web Token для того, чтобы добавить нашу подпись.

9) Отправляем наш запрос и видим, что мы залогинились под аккаунтом администратора.

Инжект собственной подписи с JWK-Параметром
JWK(JSON Web Key)- это форма представления ключа в виде JSON-объекта. При идеальном сценарии, разработчики должны прописывать свои вайтлисты с публичными ключами для верификации JWT-подписей. Однако иногда сервер принимает любые ключи, прописанные в JWK параметре.
4) Идем в уже знакомую нам вкладку JWT Editor Keys и создаем новый RSA ключ в JWK формате:

5) Идем в Repeater>JSON Web Token>Attack, выбираем Embedded JWK и в открывшемся окне выбираем наш только что созданный ключ.

6) Отправляем наш запрос и видим, что мы залогинились под аккаунтом администратора.

Инжект собственной подписи с jku-параметром
Некоторые серверы позволяют использовать параметр JKU(JWK Set URL). Часто это отдельный файл на сервере, содержащий некую связку JWK ключей в виде JSON-объекта.
Обычно они хранятся публично в /.well-known/jwks.json.
Если на сервере не прописан абсолютный путь к этому файлу или не проверяется источник, мы можем либо с помощью загрузки на сервер файла с нашими ключами, либо с помощью другого ресурса, задать наши собственные ключи в данном параметре.
4) Идем на наш сервер, создаем HTML страничку, чей сурс мы позднее будем указывать в параметр jku, и вписываем в Body наш JWK-ключ в формте jku, выглядеть это будет так:

5) Теперь меняем Header, добавляем новый параметр - jku, в него вставляем ссылку на наш эксплоит сервер:

6) С помощью Sign добавляем наш JWK, который имеется в jku.

7) Отправляем наш запрос и видим, что мы залогинились под аккаунтом администратора.

Инжект собственной подписи с kid-параметром
Некоторые системы используют разные криптографические ключи, именно поэтому серверы умеют определять, с каким типом данных они имеют дело. Для этого задается параметр kid. Kid(Key ID) может задаваться как путь к файлу с JWK связкой. Если kid параметр уязвим к directory traversal, мы можем задавать любой файл в файловой системе как ключ верификации. Эта уязвимость особо опасна при поддержке сервером симметричного алгоритма шифрования.
4) Для эксплуатации этой уязвимости нам опять понадобится создать новый симметричный ключ, где в качестве параметра "k" мы указываем нулевой байт закодированный в Base64. Чуть позже вы поймете зачем мы так делаем:


5) Теперь нам нужно поменять параметр kid. Вспомним, что в качестве ключа к подписи мы указали нулевой байт, который как раз можно получить обратившись к файлу /dev/null, так как наша машинка уязвима к directory traversal, нам лишь нужно знать примерную структуру построения сайта в файловой системе Linux, соответственно, вводим наше обновленное значение параметра kid:

6) Идем в Sign и выбираем наш симметричный ключ с "k": "AA":

7) Отправляем наш запрос и видим, что мы залогинились под аккаунтом администратора:

Чуть не забыл написать про интересный лайфхак, о котором я упомянул в начале. После получения токена идем в панель разработчика вашего браузера и во вкладке Storage>Cookies вставляем туда наш токен, можно даже заменить существующий, благодаря этому Вам не придется менять каждый ваш запрос сделанный на ресурс.
Еще несколько интересных хидеров для хакеров
1) cty(Content Type)- если вы нашли способ забайпасить верификацию подписью, этот параметр поможет поменять тип контента, например, на text/xml или application/x-java-serialized-object. Это может послужить неплохим вектором для других интересных атак типа XXE или использующих небезопасную десериализацию.
2) x5c (X.509 Certificate Chain)- этот хидер может открыть возможности для инжекта собственно подписанных сертификатов, подробнее смотрите по CVE-2017-2800, CVE-2018-2633