Bug Bounty, Bug Bounty Bootcamp, Bug Hunting

#17 Bug Bounty. Аутентификация на основе токенов. Веб-токены JSON.

Здравствуйте, дорогие друзья.


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


Эта система сопряжена с риском: если сервер использует информацию, содержащуюся в токене, для определения личности пользователя, не могут ли пользователи изменить информацию в токенах и войти в систему как кто-то другой? Чтобы предотвратить подобные атаки по подделке токенов, некоторые приложения шифруют свои токены или кодируют токен так, чтобы его могло прочитать только само приложение или другие авторизованные стороны. Если пользователь не может понять содержимое токена, он, вероятно, также не сможет эффективно его изменить. Шифрование или кодирование токена не предотвращает полностью подделку токена. Существуют способы, с помощью которых злоумышленник может подделать зашифрованный токен, не разобравшись в его содержимом. Но это намного сложнее, чем подделать токен открытого текста. Злоумышленники часто могут декодировать закодированные токены, чтобы подделать их.


Другой, более надежный способ, с помощью которого приложения защищают целостность токена, — это его подписание и проверка подписи токена при его поступлении на сервер. Подписи используются для проверки целостности части данных. Это специальные строки, которые можно сгенерировать, только если Вы знаете секретный ключ. Поскольку невозможно создать действительную подпись без секретного ключа, и только сервер знает, что такое секретный ключ, действительная подпись предполагает, что токен, вероятно, не был изменен клиентом или какой-либо третьей стороной. Хотя реализации в приложениях могут различаться, аутентификация на основе токенов работает следующим образом:

  1. Пользователь входит в систему, используя свои учетные данные.
  2. Сервер проверяет эти учетные данные и предоставляет пользователю подписанный токен.
  3. Пользователь отправляет токен при каждом запросе подтверждения своей личности.
  4. После получения и проверки токена сервер считывает идентификационную информацию пользователя из токена и отправляет в ответ конфиденциальные данные.

Веб-токены JSON


Веб-токен JSON (JWT) — один из наиболее часто используемых типов токенов аутентификации. Он состоит из трех компонентов: заголовка, полезных данных и подписи. Заголовок идентифицирует алгоритм, используемый для генерации подписи. Это строка в кодировке Base64url, содержащая имя алгоритма. Вот как выглядит заголовок JWT:


eyBhbGcgOiBIUzI1NiwgdHlwIDogSldUIH0K

Эта строка представляет собой версию этого текста в кодировке Base64url:
{ «alg»: «HS256», «typ»: «JWT» }
Раздел полезных данных содержит информацию о личности пользователя. Этот раздел также закодирован в формате Base64url перед использованием в токене. Вот пример раздела полезных данных, который представляет собой строку в кодировке Base64url


{ «имя_пользователя» : «администратор», }:
eyB1c2VyX25hbWUgOiBhZG1pbiB9Cg


Наконец, раздел подписи подтверждает, что пользователь не подделал токен. Он рассчитывается путем объединения заголовка с полезной нагрузкой, а затем его подписи с помощью алгоритма, указанного в заголовке, и секретного ключа. Вот как выглядит подпись JWT:


4Hb/6ibbViPOzq9SJflsNGPWsk6B8F6EqVrkNjpXh7M

Для этого конкретного токена подпись была создана путем подписания строки eyBhbGcgOiBIUzI1NiwgdHlwIDogSldUIH0K.eyB1c2VyX25hbWUgOiBhZG1pbiB9Cg с помощью алгоритма HS256 с использованием ключа секретного ключа. Полный токен объединяет каждый раздел (заголовок, полезные данные и подпись), разделяя их точкой (.):


eyBhbGcgOiBIUzI1NiwgdHlwIDogSldUIH0K.eyB1c2VyX25hbWUgOiBhZG1pbiB9Cg.4Hb/6ibbVi
POzq9SJflsNGPWsk6B8F6EqVrkNjpXh7M

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


Манипулирование полем alg

Иногда приложениям не удается проверить подпись токена после его прибытия на сервер. Это позволяет злоумышленнику просто обойти механизм безопасности, предоставив недействительную или пустую подпись.
Один из способов, с помощью которого злоумышленники могут подделать свои собственные токены, — это подделать поле alg заголовка токена, в котором указан алгоритм, используемый для кодирования подписи. Если приложение не ограничивает тип алгоритма, используемого в JWT, злоумышленник может указать, какой алгоритм использовать, что может поставить под угрозу безопасность токена.
JWT поддерживает опцию none для типа алгоритма. Если для поля alg установлено значение none, даже токены с пустыми разделами подписи будут считаться действительными. Рассмотрим, например, следующий токен:


eyAiYWxnIiA6ICJOb25lIiwgInR5cCIgOiAiSldUIiB9Cg.eyB1c2VyX25hbWUgOiBhZG1pbiB9Cg


Этот токен представляет собой просто версии этих двух больших двоичных объектов в кодировке Base64url без подписи:


{ «alg»: «none», «typ»: «JWT» } { «user»: «admin» }

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


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


Теперь предположим, что приложение изначально было разработано для использования токенов RSA. Токены подписываются закрытым ключом А, который хранится в секрете от общественности. Затем токены проверяются открытым ключом B, который доступен каждому. Это нормально, если токены всегда рассматриваются как токены RSA. Теперь, если злоумышленник изменит поле alg на HMAC, он сможет создавать действительные токены, подписывая поддельные токены открытым ключом RSA, B. Когда алгоритм подписи переключается на HMAC, токен по-прежнему проверяется с помощью открытого ключа RSA. ключ B, но на этот раз токен можно подписать тем же открытым ключом.


Подбор ключа

Также можно было бы угадать или перебрать ключ, используемый для подписи JWT. Для начала у злоумышленника есть много информации: алгоритм, использованный для подписи токена, подписанные полезные данные и полученная подпись.
Если ключ, используемый для подписи токена, недостаточно сложен, они могут легко подобрать его методом перебора. Если злоумышленник не может подобрать ключ, он может вместо этого попытаться раскрыть секретный ключ. Если существует другая уязвимость, такая как обход каталога, атака внешнего объекта (XXE) или SSRF, которая позволяет злоумышленнику прочитать файл, в котором хранится значение ключа, злоумышленник может украсть ключ и подписать произвольные токены по своему выбору. Мы поговорим об этих уязвимостях в следующих разделах.


Чтение конфиденциальной информации

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

Политика одного и того же происхождения


Политика одного и того же происхождения (SOP) — это правило, которое ограничивает то, как скрипт из одного источника может взаимодействовать с ресурсами другого происхождения. В одном предложении SOP таков: сценарий со страницы А может получить доступ к данным со страницы Б, только если страницы имеют одно и то же происхождение. Это правило защищает современные веб-приложения и предотвращает множество распространенных веб-уязвимостей.
Говорят, что два URL-адреса имеют одно и то же происхождение, если они используют один и тот же протокол, имя хоста и номер порта. Давайте посмотрим на несколько примеров. Страница А находится по этому URL:


https://medium.com/@user

Он использует HTTPS, который, как помните, по умолчанию использует порт 443. Теперь просмотрите следующие страницы, чтобы определить, какая из них имеет то же происхождение, что и страница А, согласно SOP:


https://medium.com/ http://medium.com/ https://twitter.com/@user https://medium.com:8080/@user

URL-адрес https://medium.com/ имеет то же происхождение, что и страница A, поскольку обе страницы имеют один и тот же источник, протокол, имя хоста и номер порта. Остальные три страницы имеют другое происхождение, чем страница А. http://medium.com/ имеет другое происхождение, чем страница А, поскольку их протоколы различаются. https://medium.com/ использует HTTPS.
Это всего лишь несколько примеров проблем безопасности JWT. Для получения дополнительных примеров уязвимостей JWT используйте поисковый запрос «Проблемы безопасности JWT». Безопасность любого механизма аутентификации зависит не только от его конструкции, но и от его реализации. JWT могут быть безопасными, но только при правильной реализации.
https://twitter.com/@user также имеет другое происхождение, поскольку у него другое имя хоста. Наконец, https://medium.com:8080/@user имеет другое происхождение, поскольку использует порт 8080 вместо порта 443.
Теперь давайте рассмотрим пример, чтобы увидеть, как SOP нас защищает. Представьте, что Вы вошли на свой банковский сайт onlinebank.com. К сожалению, вы нажимаете на вредоносный сайт Attacker.com в том же браузере.
Вредоносный сайт отправляет GET-запрос на сайт onlinebank.com для получения вашей личной информации. Поскольку вы вошли в банк, ваш браузер автоматически включает файлы cookie в каждый запрос, который вы отправляете на onlinebank.com, даже если запрос генерируется сценарием на вредоносном сайте. Поскольку запрос содержит действительный идентификатор сеанса, сервер onlinebank .com выполняет запрос, отправляя HTML-страницу, содержащую вашу информацию. Затем вредоносный скрипт считывает и извлекает частные адреса электронной почты, домашние адреса и банковскую информацию, содержащуюся на странице.
К счастью, SOP не позволит вредоносному сценарию, размещенному на Attacker.com, прочитать HTML-данные, возвращенные с onlinebank.com. Это не позволяет вредоносному сценарию на странице А получить конфиденциальную информацию, встроенную в страницу Б.


Научитесь программировать


Теперь у Вас должен быть солидный опыт, который поможет Вам понять большинство уязвимостей, которые мы рассмотрим. Прежде чем настраивать свои хакерские инструменты, я рекомендую Вам научиться программировать. Навыки программирования полезны, поскольку поиск ошибок включает в себя множество повторяющихся задач, а изучив язык программирования, такой как Python, или написание сценариев оболочки, Вы сможете автоматизировать эти задачи, чтобы сэкономить много времени.


Вам также следует научиться читать JavaScript — язык, на котором написано большинство сайтов. Чтение JavaScript сайта может научить Вас тому, как он работает, и ускорить поиск ошибок. Многие ведущие хакеры говорят, что их секретный соус заключается в том, что они читают JavaScript и ищут скрытые конечные точки, небезопасную логику программирования и секретные ключи. Я также обнаружил множество уязвимостей, читая исходный код JavaScript.
Codecademy — хороший ресурс для обучения программированию. Если Вы предпочитаете вместо этого прочитать книгу, книга Зеда Шоу «Изучите Python на собственном горьком опыте» (Addison-Wesley Professional, 2013) — отличный способ изучить Python. А чтение книги «Красноречивый JavaScript, третье издание» Марины Хавербеке (No Starch Press, 2019) — один из лучших способов освоить JavaScript.

На этом все. Всем хорошего дня.

Цикл статей по Bug Bounty.