В прошлый раз мы рассказали о том, что такое платформы и программы багбаунти, какой базовый инструментарий может использовать багхантер, чтобы облегчить или автоматизировать поиск, привели реальные примеры уязвимостей из старых версий приложений с открытым исходным кодом и посоветовали хорошую литературу для самостоятельного изучения.
В этой статье поговорим о том, что такое скоуп (scope) — устанавливаемые программой границы, в рамках которых разрешается проводить багхантинг, — как работать со скоупом и какие инструменты могут быть полезны. Кроме того, покажем несколько реальных примеров уязвимостей других классов, а в конце вас ждет небольшой бонусный раздел.
Дисклеймер
Имейте в виду, эта статья носит информационный характер и посвящена легальному поиску уязвимостей в информационных системах. Мы не призываем к совершению противоправных действий и обращаем внимание третьих лиц на необходимость во всех случаях соблюдать действующее законодательство и правила соответствующей программы по поиску уязвимостей. Неправомерный доступ к компьютерной информации влечет за собой юридическую ответственность.
Скоуп
Компании, размещающие свои программы на платформах багбаунти, как правило, указывают скоуп, или область действия, в рамках которой багхантеры должны проводить свои исследования. Такие работы будут считаться легитимными и легальными при условии, что багхантеры будут выполнять и остальные требования программы.
Например, в программе багбаунти Positive Technologies при проведении работ запрещено:
разглашать информацию о найденной уязвимости без разрешения компании;
воздействовать на учетные записи пользователей без их разрешения;
использовать обнаруженную уязвимость в личных целях;
использовать инструменты тестирования уязвимостей, автоматически генерирующие значительные объемы трафика и приводящие к атакам с исчерпанием ресурсов;
проводить атаки, наносящие вред целостности и доступности сервисов (например, DoS-атаки, брутфорс-атаки), пытаться эксплуатировать уязвимость, нацеленную на исчерпание ресурсов;
проводить физические атаки на персонал, дата-центры и офисы компании;
проводить атаки на системы Positive Technologies с использованием техник социальной инженерии (фишинг, вишинг и т. д.) и спам-рассылок клиентам, партнерам и сотрудникам;
исследовать серверную инфраструктуру, где размещены веб-приложения.
Cкоуп Positive Technologies включает пять доменов (ptsecurity.com, partners.ptsecurity.ru, group.ptsecurity.com, event.phdays.com, promo.ptsecurity.com).
Остановимся подробнее на том, что такое домен, субдомен и как их искать.
Домен (доменный адрес) — уникальный человекочитаемый адрес веб-сервера в сети, который связан с целевым или проксирующим IP-адресом сервера. Примеры доменов: XXX.com и XXX.ru.
Субдомен (поддомен) — отдельный домен, как правило третьего уровня и выше, являющийся частью домена более высокого уровня, как правило второго. Примеры субдоменов: api.XXX.com и login.XX.com.
Существует большое количество способов поиска субдоменов. Приведем некоторые из них:
анализ отдаваемого сервером кода веб-страницы или анализ исходного кода мобильного приложения для поиска конечных точек субдоменов в комментариях страницы, в адресах подключаемых скриптов и их содержимом, в забытых файлах;
Google Dork Queries — выполнение в поисковой системе Google специальных запросов, помогающих раскрыть дополнительную информацию;
веб-сервисы, специализирующиеся в том числе на поиске субдоменов: crt.sh, virustotal.com, searchdns.netcraft.com, dnsdumpster.com, www.shodan.io;
инструменты, собирающие субдомены из разных источников: Sublist3r (github.com/aboul3la/Sublist3r), crtsh (github.com/YashGoti/crtsh), Amass (github.com/OWASP/Amass);
перебор доменов методом брутфорса (brute force): subbrute (github.com/TheRook/subbrute), dnsrecon (www.kali.org/tools/dnsrecon), ffuf (github.com/ffuf/ffuf), nmap (nmap.org).
Другим примером на Standoff 365 Bug Bounty может служить программа компании ВКонтакте. В ее скоуп входят следующие домены: *.vk.com, vk.com, m.vk.com, api.vk.com, login.vk.com, oauth.vk.com, *.vk.me, *.vk.cc, *.vk.link, id.vk.com, *.vkontakte.(ru|com), *.vk-cdn.net, *.userapi.com, *.vkuser.net, *.vkuseraudio.(com|net), *.vkuservideo.(com|net), *.vkuserlive.(com|net).
Примечательный момент в скоупе этой программы — наличие звездочки в названиях доменов. Когда участвующая в программе багбаунти компания имеет большое количество субдоменов и все они входят в скоуп, перед названием домена ставится звездочка: *.vk.com.
Не стоит забывать о том, что в правилах программы багбаунти могут быть и дополнительные требования. К примеру, в исключения могут попасть тестовые домены, домены, делегированные партнерскими сервисами (за них текущая программа ответственности не несет), а также те, которые специально вывели из области действия.
Подводя итоги этого раздела, еще раз напомним, что, прежде чем приступать к поиску уязвимостей в разрешенном скоупе, необходимо внимательно ознакомиться со всеми правилами программы багбаунти. Приобретение и совершенствование навыков по поиску субдоменов, находящихся в скоупе программ, и дальнейшее выявление уязвимостей в них, могут принести багхантерам значимую награду в виде накопленного опыта, репутации на платформе и денежного вознаграждения.
Примеры часто встречающихся уязвимостей
В предыдущей статье мы рассмотрели атаки типа SQL injection, cross-site scripting (XSS) и cross-site request forgery (CSRF). В этом материале разберем следующие уязвимости:
insecure direct object references (IDOR) — уязвимость, позволяющая приложению использовать контролируемые пользователем данные для получения прямого доступа к объектам. Другими словами, эксплуатация этой уязвимости в системе может привести к утечке пользовательских данных или выполнению несанкционированного действия — добавлению, чтению, обновлению или удалению какой-либо информации в системе;
directory traversal — уязвимость, позволяющая злоумышленнику выйти за пределы разрешенного каталога и производить удаление, изменение или чтение произвольных файлов на сервере. В результате ее эксплуатации могут быть прочитаны системные файлы либо файлы приложения, которые раскроют злоумышленнику исходный код; файлы с переменными окружения, содержащими токены для подписи или данные для авторизации, например для базы данных или аккаунта администратора, а также любую другую критическую информацию, которая ни в коем случае не должна быть в открытом доступе.
Быстрый старт на настоящих примерах
Чтобы успешно заниматься поиском уязвимостей в рамках багбаунти, необходимо фундаментальное понимание того, каким образом возникают уязвимости, где они могут находиться и как их эксплуатировать для представления доказательств работы. В примерах этого раздела будут использоваться устаревшие и уязвимые плагины для одной из популярнейших систем управления содержимым — WordPress.
Insecure direct object references
Начнем с примера уязвимости класса insecure direct object references (IDOR). Для ее демонстрации выбран плагин для WordPress — Directorist версии 7.4.2.1 с общедоступным эксплойтом. Суть рассматриваемой уязвимости в том, что авторизованный пользователь даже с минимальными правами может изменить пароль любого другого пользователя, в том числе администратора.
В папке с плагином находится файл includes/classes/class-ajax-handler.php, в котором в функции update_user_profile в строке 850 вызывается функция directorist_update_profile; внутри нее вызывается еще одна функция — update_profile, которая обновляет информацию о пользователе с учетом полученных извне данных.
В функции update_profile обратите внимание на строку 486, где используется тернарный оператор для получения значения идентификатора пользователя. В случае если пользователь передает значение в ключе user[ID] при выполнении POST-запроса, берется это передаваемое значение. В ином случае — результат функции get_current_user_id(), что будет являться идентификатором текущего пользователя.
Другим любопытным моментом являются строки 500–501, в которых задается новый пароль для пользователя. В строке 518 вызывается функция wp_set_password, которая обновляет пароль пользователя в соответствии с данными, которые контролируются извне.
В этом случае пользователь с ролью «Подписчик» может выполнить POST-запрос к сценарию /wp-admin/admin-ajax.php?action=update_user_profile и передать в теле запроса данные, приведенные ниже, с указанием ID пользователя. Как правило, пользователь с ролью «Администратор» имеет идентификатор со значением «1».
Результатом будет несанкционированное изменение пароля пользователя с ролью «Администратор» при использовании плагина Directorist версии 7.4.2.1.
Directory traversal
Рассмотрим другой класс уязвимостей — directory traversal. Примером будет служить уязвимый плагин для WordPress — Simple Job Board версии 2.9.3. Для этой версии плагина существует общедоступный эксплойт. Суть рассматриваемой уязвимости заключается в том, что из-за неправильной обработки пользовательского ввода при получении файла с резюме злоумышленник может выйти за пределы разрешенного каталога и прочитать системный файл.
В папке с плагином расположен файл includes/class-simple-job-board-resume-download-handler.php; в функции download_resume в строке 49 этого файла формируется путь к файлу через глобальную переменную $_GET['sjb_file'], значение которой контролирует пользователь.
Видно, что эта переменная обрабатывается функцией esc_attr, однако использование данной функции в этом случае некорректно, потому что она предназначена для экранирования HTML-атрибутов, а именно спецсимволов <, >, &, " и '.
Для выполнения атаки directory traversal достаточно специальных символов . (точка) и / (косая черта), чтобы выйти за пределы текущей директории и обратиться к системным файлам или файлам приложения.
Поэтому пользователь с ролью «Редактор» может отправить на сервер запрос, описанный в статье с общедоступным эксплойтом, и в ответ получить системный файл, к которому доступа быть не должно. В данном случае происходит попытка получения системного файла /etc/passwd:
Сервер возвращает запрашиваемый злоумышленником системный файл:
Бонус
Пришло время вспомнить один из классов уязвимостей, который мы рассматривали в первой части статьи «Как начать заниматься багхантингом веб-приложений»: некорректную санитизацию данных при генерировании веб-страниц (межсайтовое выполнение сценариев (XSS), или, простыми словами, выполнение вредоносного JavaScript-кода в браузере жертвы).
В этом разделе расскажем про XSS-атаку postMessage и наше исследование под названием Fuzzing for XSS via nested parsers condition.
PostMessage XSS
Существует понятие postMessage. Это механизм отправки кросс-доменных запросов между сайтами. К примеру, есть некоторый сайт, у которого есть слушатель сообщений postMessage. Задача этого слушателя — обработать поступающее извне сообщение. Обработка может быть совершенно разной: работа с файлами куки, выполнение редиректа на произвольную страницу, модификация HTML-страницы и т. п. И существует другой сайт, способный запустить в iframe или открыть в новой вкладке целевой сайт, у которого есть слушатель сообщений, и передавать туда данные с помощью механизма postMessage. В некоторых случаях киберпреступник может воспользоваться этими функциями, чтобы выполнить так называемую атаку postMessage XSS.
Приведем небольшой пример того, как злоумышленник может использовать в своих целях функцию слушателя сообщений postMessage.
На странице есть код JavaScript, который устанавливает слушателя сообщений с помощью функции receiveMessage. В начале этой функции проверяется источник сообщения: с какого домена оно пришло. Если источником сообщения является домен, начинающийся на https://application.localhost, приложение продолжает работать: происходит парсинг строки с помощью функции JSON.parse в переменную data, после чего проверяется, есть ли в объекте ключ url, и, если он есть, выполняется редирект на страницу, которая и указана в значении data.url. Рассмотрим, как атакующие могут злоупотребить этой функциональностью на целевом сайте.
Во-первых, в коде содержится проверка источника сообщения: событие с сообщением должно быть отправлено с домена, имя которого начинается на https://application.localhost. Однако злоумышленник может обойти это условие, если сообщение будет отправлено с сайта, который он контролирует, например с https://application.localhost.evil.localhost.
Во-вторых, после того как прошла проверка origin (источника сообщения), злоумышленник мог поместить в ключ url значение javascript:alert(). При присваивании этого значения в location.href будет выполнена JavaScript-функция alert в браузере жертвы.
Злоумышленник размещает на своем сайте, который находится по адресу https://application.localhost.evil.localhost, следующую полезную нагрузку и заманивает на него жертву с помощью фишинга:
После того как жертва перешла на сайт злоумышленника https://application.localhost.evil.localhost и разрешила всплывающее окно, откроется новая вкладка в домене https://application.localhost. В открывшуюся вкладку в домене https://application.localhost спустя 1 секунду с сайта злоумышленника будет отправлено сообщение postMessage в виде строки '{"url":"javascript:alert()"}', что приведет к атаке postMessage XSS, или, другими словами, выполнению произвольного JavaScript-кода в браузере жертвы. Задержка в одну секунду обусловлена тем, что открываемому сайту необходимо дать полностью прогрузиться.
Возможны ситуации, когда в найденном слушателе сообщений postMessage может отсутствовать проверка на источник отправления (origin) либо эта проверка может быть недостаточно корректна, как это описано в примере выше. Дополнительно рекомендуем почитать о других способах обхода защитных механизмов в статье PostMessage vulnerabilities.
Стоит помнить еще и о том, что слушатели сообщений могут находиться не только на главной странице сайта, но и в подключаемых скриптах, в том числе сторонних. Чтобы найти их для проверки защищенности, следует либо вручную искать во всех подключаемых на страницу скриптах установку слушателя сообщения, либо использовать автоматизированное средство, определяющее, где могут находиться слушатели сообщений.
К автоматизированным средствам, помогающим находить слушатели postMessage, можно отнести плагин postMessage-tracker для браузера Google Chrome.
Fuzzing for XSS via nested parsers condition
Некоторое время назад мы опубликовали исследование Fuzzing for XSS via nested parsers condition. Мы выяснили, что при использовании определенного языка разметки и библиотеки парсинга к нему, например BBCode, можно внедрить такую синтаксическую конструкцию, которая запутает парсер разметки и позволит внедрить код JavaScript в результат парсинга (причем даже с условием того, что одной из задач парсера как раз и является недопущение внедрения JavaScript-кода в результат его работы). Полученный результат может быть отображен на странице пользователя, что приведет к XSS-атаке на него.
Вот реальный пример из нашего исследования, базирующийся на популярном бесплатном веб-форумном движке MyBB. В версии 1.8.25 команда разработки MyBB исправила синтаксическую конструкцию следующего вида, приводящую к XSS-атаке:
После ее исправления мы выпустили еще одно исследование — MyBB <= 1.8.31: Remote Code Execution Chain. В нем была обнаружена и продемонстрирована еще одна синтаксическая конструкция, которая запутывает парсер и тоже приводит к XSS-атаке на пользователя. Она имеет следующий вид:[email][email= onpointerover=alert()//]text[/email]
Приведенную выше синтаксическую конструкцию злоумышленник внедряет в свою подпись (сигнатуру) на форуме в режиме исходного кода и сохраняет ее.
Если после сохранения просмотреть данную сигнатуру в обычном режиме, в котором уже будет использован парсер для обработки внедренной пользователем нагрузки, то произойдет запутывание парсера и будет выполнен выход за пределы значения атрибута в виде события onpointerover и его значения — JavaScript-функции alert().
Поэтому при багхантинге или анализе защищенности веб-приложений не стоит забывать о наших примерах в бонусном разделе????
Заключение
В конце нам хотелось бы обратить внимание багхантеров, особенно начинающих, на некоторые важные вещи:
при поиске уязвимостей необходимо очень внимательно прочитать правила программы на площадке багбаунти, тщательно изучить разрешенный скоуп и дополнительные условия;
при нахождении уязвимости или возможности проведения атаки в момент написания отчета прикладывать доказательство работы (PoC), обосновывая влияние на безопасность системы;
помнить, что, помимо уязвимостей, которые могут быть в самописных тестируемых системах, на других портах домена или субдомена также могут быть устаревшие версии систем, в которых тоже могут присутствовать известные уязвимости различного рода. О них также следует сразу сообщать компании;
необходимо искать новые техники эксплуатации уязвимостей и исследовательские подходы, постоянно углублять свои знания, фундаментально изучать, какие классы уязвимостей существуют, как их находить, и стараться понять, как их можно исправить.
Таким способом исследователи в сфере кибербезопасности помогают выявлять возможности проведения кибератак и своевременно предотвращать их, нивелировать возможные риски, повышать надежность сервисов, которыми пользуются миллионы людей, и делать мир вокруг безопаснее.
Алексей Соловьев
Старший специалист группы анализа защищенности веб-приложений компании Positive Technologies