IDOR. Autorize. Broken Access Control.
Уязвимости IDOR (Insecure direct object references) и Broken Access Control (BAC) являются одними из самых опасных уязвимостей в веб-приложениях. Они позволяют злоумышленнику получить доступ к конфиденциальным данным или функциям, к которым он не должен иметь доступа.
Что такое BAC и IDOR?
Все прекрасно знают о том, что авторизация предоставляет пользователю права на выполнение определённых действий, а также процесс проверки (подтверждения) данных прав при попытке выполнения этих действий. Авторизация не эквивалентна аутентификации. После успешной аутентификации авторизация определяет, к каким функциям и данным может получить доступ пользователь, обеспечивая при этом надлежащее разграничение прав доступа.
Именно поэтому веб-приложению необходимы средства контроля доступа, позволяющие его пользователям использовать веб-приложение с различными привилегиями. Контроль доступа — это применение ограничений на то, кто (или что) может выполнять различные функции и получать доступ к запрошенным ресурсам. Нарушенный контроль доступа (Broken Access Control) — часто встречающаяся уязвимость в системе безопасности веб-приложений. Существуют несколько типов контроля доступа, а вместе с ними и уязвимостей, связанных с их нарушением:
- Вертикальный контроль доступа;
- Горизонтальный контроль доступа;
- Контекстно-зависимый контроль доступа.
Про горизонтальный контроль доступа мы поговорим подробнее.
IDOR, или небезопасные прямые ссылки на объекты — это тип уязвимости контроля доступа, которая возникает, когда приложение использует вводимые пользователем данные для прямого доступа к объектам. Термин IDOR стал популяризирован после его появления в первой десятке OWASP 2007 года. Однако это лишь один пример многих ошибок реализации контроля доступа, которые могут привести к его обходу. Уязвимости IDOR чаще всего связаны с горизонтальным повышением привилегий, но они также могут привести к вертикальному повышению привилегий, получив, например, учетные данные администратора путём эксплуатации уязвимой конечной точки.
В этой статье мы рассмотрим принцип работы уязвимостей IDOR и Broken Access Control, а также методы их обнаружения и автоматизации с помощью Autorize.
Как искать
Для автоматизации поиска уязвимости IDOR нам необходимо наличие двух аккаунтов.
Создаём два аккаунта, воспользовавшись расширением для Firefox под названием Multi-Account-Container, которое позволяет нам открывать несколько сессий в одном окне браузера:
Советую использовать данное расширение, так как оно очень часто может помочь в ситуациях, когда необходим режим инкогнито или другой браузер для проверки каких-либо уязвимостей.
Дополнительно устанавливаем расширение под названием Autorize для Burp Suite:
Добавляем сессионный идентификатор атакующего
Первое, что вам нужно сделать — это добавить сессионный идентификатор второго пользователя или злоумышленника в Autorize.
Если вы не уверены, какие заголовки вам точно необходимы, то можно скопировать большую часть запроса и использовать его, ведь лучше копировать больше заголовков, чем меньше:
Теперь просто копируем заголовки запроса атакующего и вставляем в Autorize:
Больше второй аккаунт нам не понадобится, и мы можем переходить к поиску нарушений контроля доступа, но сначала я объясню, как работает Autorize:
Всякий раз, когда совершается запрос, расширение будет менять его и подставлять добавленный нами сессионный идентификатор и проверять различия в ответах. Например, если я попытаюсь добавить какой-то товар в корзину, Autorize поменяет часть запроса и попробует совершить то же действие с сессионным идентификатором атакующего.
Таким образом, мы будем пытаться получить содержимое данных, принадлежащих другому пользователю, то есть проверять веб-приложение на наличие IDOR.
По сути, расширение делает то же самое, что и Repeater, но подставляет каждый раз другие заголовки в запрос.
Теперь какую бы функциональность мы не проверяли, Autorize каждый раз будет отправлять наш запрос, но с другими заголовками.
Можно переходить к тестированию контроля доступа и поиска уязвимости IDOR. Просто используем все доступные функциональности и изучаем работу сайта.
Detect
Как можно заметить, после добавления товара в корзину приложение говорит нам, что мы просмотрели корзину другого пользователя:
Перейдем в Autorize и посмотрим, в каком запросе у нас нарушается контроль доступа:
Как вы видите, сессионный идентификатор отличается, и можно заметить, что ответ приложения одинаков при разных заголовках запроса, тогда как у запроса без заголовков авторизации ответ отличается:
Autorize совершает две проверки:
- Добавляет заголовки атакующего в запрос;
- Удаляет заголовки, сигнализирующие об успешной авторизации (то есть отправляет запрос без заголовков).
Вторая проверка также является нарушением контроля доступа, так как позволяет получить информацию неавторизованному пользователю.
Советую чаще проверять конечные точки, содержащие pdf или какие-либо файлы, так как потенциально они могут не иметь проверки контроля доступа и обычно защищены уникальным идентификатором, полагаясь на безопасность за счет непредсказуемости идентификатора.
Таким образом, мы проверили всю функциональность покупки на наличие уязвимостей IDOR и Broken Access Control в автоматическом режиме, и Autorize показал нам результат работы в удобном для чтения и восприятия формате.
Теперь вернёмся к Authorize и посмотрим, где нам удалось обойти ограничения контроля доступа:
Как можно подметить, длина ответа приложения с разными сессионными данными одинаковая. Это говорит нам о том, что в данном месте есть IDOR, и мы получаем доступ к данным другого пользователя (в данном случае чек после размещения заказа), которые содержат конфиденциальную информацию.
Как я и говорил, статические файлы в большинстве случаев могут быть не защищены проверкой контроля доступа и будут доступны по уникальному идентификатору.
Сравниваем содержимое pdf с помощью Comparer, чтобы убедиться, что мы получили доступ к одному и тому же чеку:
Переходим в браузере в аккаунт атакующего и смотрим содержимое чека:
В другом запросе также раскрывается email другого пользователя:
Также по длине ответа можно понять, в каких запросах расишрению не удалось обойти ограничения:
IDOR bypass BugBounty
Закончим с теоретической частью и для примера рассмотрим лабораторную работу, посвященную найденной исследователем IDOR-уязвимости в рамках программы BugBounty.
В данной лабораторной показан пример слабого шифрования и возможности обхода ограничения скорости перебора значений и защиты от ботов.
Скачиваем лабораторную работу:
git clone https://github.com/leetCipher/bug-bounty-labs.git
Запускаем уязвимое приложение:
sudo docker-compose up
Сервис, где была обнаружена уязвимость, похож на Instagram, где можно публиковать фотографии и делиться ими.
Когда я проверил все конечные точки, то обратил внимание на вызов метода /api/user, в теле которого находился параметр, благодаря которому можно просмотреть учетные данные конкретного пользователя:
Простой перебор данного идентификатора невозможен из-за количества символов, и на первый взгляд может показаться, что всё безопасно и никакого IDOR нет. Но на сайте мной была обнаружена конечная точка /js/register.js, которая показывает, как происходит формирование данного хэша:
Так как в формировании хэша участвует дата регистрации, first_name и last_name, то единственное, что нам нужно угадать, — это дата. Ниже приведён скрипт, который может подобрать все варианты хэша для заданных имени имени и фамилии:
#!/usr/bin/python3 import hashlib import sys def main(first_name, last_name): # hashes wordlist wordlist_fd = open("hashes-wordlist.txt", "w") # user full name reversed full_name = first_name + last_name full_name = full_name[::-1] # brute-force all dates since 2017 for year in range(2017, 2023, 1): for month in range(1, 13): for day in range(1, 32): string = "{}{:02}{:02}{}".format(full_name, day, month, year) # generate the SHA-256 sum of the reversed full name and the date hashed_string = hashlib.sha256(string.encode()).hexdigest() # write the hash to the hashes-wordlist.txt file wordlist_fd.write("{}\n".format(hashed_string)) # close the fd wordlist_fd.close() print("[+] wordlist generated for {} {}".format(first_name, last_name)) if __name__ == "__main__": if len(sys.argv) == 3: main(str(sys.argv[1]), str(sys.argv[2])) else: print("usage: ./generate-hashes.py ")
Исследователь обнаружил, что домен с уязвимым приложением был зарегистрирован в 2017 году. Это значит, что отсчет даты регистрации пользователей можно начинать с этого года:
Приведённый выше скрипт подбирает хэши на основе двух значений: first_name и last_name. Он объединяет (конкатенирует) имя и фамилию в переменную full_name, а затем перебирает все даты, начиная с 2017 года. Затем вся информация объединяется в переменную string и вычисляется хэш SHA256 в шестрадцатеричной кодировке для этой строки. Результат вычисления вероятных значений хэша для конкретного пользователя записывается в файл hashshes-wordlists.txt.
Теперь можно попробовать перебрать хэш пользователя john doe, имя которого раскрывается на странице:
Получаем возможные хэши пользователя:
Переходим в Intruder и пробуем перебрать все значения:
Спустя 20 запросов мы получаем ограничения на попытку просмотра данных:
Кастомные заголовки не помогли обойти ограничения, но исследователем было замечено, что при смене заголовка Referer ограничения снимаются, и мы можем продолжать проверку хэша:
Таким образом, в Intruder добавляем точку перебора в заголовок Referer (его значение не играет особой роли):
После атаки получаем доступ к данным пользователя john doe:
Повторим атака с именем sam young:
Таким образом, исследователю удалось найти изъян в механизме генерации хэша пользователя, что позволило проэксплуатировать уязвимость IDOR в, казалось бы, неуязвимом приложении.