Найти в Дзене
B0rn2beR00T

Решение PortSwigger (JWT authentication bypass via flawed signature verification)

Приветствую, друзья! Продолжаем разбирать различные приёмы с обходом защиты JWT-токена. На этот раз мы повысим свои привилегии и зайдём в панель администратора путём сбрасывания алгоритма подписи токена и удаления самой подписи. Приступим к работу! Для начала авторизируемся под учётной записью wiener, которого нам выдают в описании таска: Перехватив запрос при залогинивании пользователя в Burp Suite видим приобретенный в заголовке Cookie JWT-токен. Давайте проверим корректно ли принимает его сервер, попробовав убрать подпись. Для того, чтобы хорошо понимать суть атаки давайте разберёмся подробнее в структуре JWT-токена: JWT=<Заголовок>.<Полезная нагрузка>.<Подпись> Для того, чтобы проверить уязвим ли хост к данной атаке, нужно провести манипуляции, которые будут указаны далее по тексту. Предварительно по ответам сервера уязвимость увидеть нельзя (как это бывает например с SQLi). Для начала выделим часть токена с заголовком и посмотрим что там храниться. В разборе мы будем пользоваться
Оглавление

Приветствую, друзья!

-2

Продолжаем разбирать различные приёмы с обходом защиты JWT-токена. На этот раз мы повысим свои привилегии и зайдём в панель администратора путём сбрасывания алгоритма подписи токена и удаления самой подписи. Приступим к работу!

Сбор информации

Для начала авторизируемся под учётной записью wiener, которого нам выдают в описании таска:

-3

Перехватив запрос при залогинивании пользователя в Burp Suite видим приобретенный в заголовке Cookie JWT-токен. Давайте проверим корректно ли принимает его сервер, попробовав убрать подпись.

-4

Структура JWT-токена

Для того, чтобы хорошо понимать суть атаки давайте разберёмся подробнее в структуре JWT-токена:

-5

JWT=<Заголовок>.<Полезная нагрузка>.<Подпись>

  • В заголовке храниться служебная информация о токене (алгоритм подписи, тип токена)
  • Полезная нагрузка содержит сведения о пользователе (логин, id, права пользователя, время создания токена)
  • Подпись формируется за счёт конкатенации заголовка и полезной нагрузки в кодировке Base64, что далее подписывается секретным ключом. При изменении полезной нагрузки или заголовка, подпись не будет совпадать с другими частями и в итоге не примется сервером.

Крутим JWT

Для того, чтобы проверить уязвим ли хост к данной атаке, нужно провести манипуляции, которые будут указаны далее по тексту. Предварительно по ответам сервера уязвимость увидеть нельзя (как это бывает например с SQLi).

Для начала выделим часть токена с заголовком и посмотрим что там храниться. В разборе мы будем пользоваться только Burp Suite, но никто не запрещает вам воспользоваться также удобными веб-инструментами jwt.io или же xjwt.io.

-6

В правой части Burp Suite видим декодированные из base64 данные заголовка токена:

-7

Разберёмся с параметрами заголовка:

  • kid — это имя ключа, которым подписан токен.
  • alg — это алгоритм, которым токен подписан.

Тут нам необходимо изменить параметр alg:RS256 на none. Таким образом сбрасываем алгоритм подписи токена. Чтобы изменения применились тыкаем на Apply changes.

Далее переходим к полезной нагрузке токена:

-8

Видим, что тут лежит информация о пользователе, кто издатель токена и когда был создан. Теперь подробнее:

  • iss — это "issuer", то есть кто выдал токен.
  • exp — это время, когда токен истекает (expiration time).
  • sub — это "subject", то есть тот, кому принадлежит токен.
-9

Тут нам нужно поменять параметр sub и вписать туда значение administrator. Что повысит наши привилегии. Таким образом, у вас должно быть что-то подобное:

-10
-11

Убираем 3-ю часть токена, но оставляем точку, которая стояла в начале подписи. Далее попробуем сделать GET-запрос на /admin, которой у нас не было доступа от лица wiener.

-12

Теперь у нас есть доступ к админской панели т.к. мы повысили свои привилегии. Теперь можем удалить беднягу carlos и решить таск.

-13

Победа!

Упрощаем работу с JWT

Для более удобной реализации такой атаки установим расширение для Burp Sute JSON Web Tokens. Расширения доступны в Pro-версии тулзы.

-14

Расширение будет подсвечивать запросы, где фигурирует JWT-токен.

-15

Забросим этот запрос в Repeater и перейдём во кладку JSON Web Tokens.

-16

Здесь мы проделываем ровно те же действия, но теперь можем выбрать в панели alg:none, что автоматически уберёт подпись и изменить параметр alg. Нам же только остаётся руками поменять параметр sub.

-17

Также топаем на /admin:

-18

И видим, что у нас есть доступ, как и в предыдущий раз, но нам пришлось сделать меньше телодвижений. Так намного удобней :)

-19

Выводы

JWT сам по себе надёжный, если его правильно использовать и уверен, что он вписывается в структуру выстроенной системы. Если у вас куча серверов, а JWT хорош в масштабировании, то это хороший выбор. Если есть сомнения, то всегда есть session ID, в которых учитывается состояние сессии.

  • Stateful (c состоянием): сервер помнит, кто ты.
    Пример: серверу нужно хранить твои данные где-то (сессии в базе).
  • Stateless (без состояния): сервер ничего не помнит, всё приходит в каждом запросе.
    Пример: JWT — всё, что нужно, уже в токене.

Лучшей защитой от такого вектора будет указать в фреймворке чёткий список поддерживаемых алгоритмов подписи и исключить значение none. Также не будет ошибкой использовать токена с малым временем жизни. Злоумышленник не успеет воспользоваться токеном как он уже протухнет.

Спасибо за внимание! Не забывайте оценивать моё творчество лайком. Всех благ!