Эксплуатация cookie-based XSS | $2300 Bug Bounty story

⠀Уже на протяжении довольно длительного времени я охочусь за уязвимостями на платформе HackerOne, выделяю некоторое количество времени вне основной работы, чтобы проверить любимые и новые программы. Бесчисленное количество раз приходилось натыкаться на cookie-based XSS уязвимость, которая и станет главной героиней этой статьи. Данный тип уязвимости возникает, когда значение параметра cookie рефлектится на страницу. По умолчанию они считаются self-XSS, если мы, в свою очередь, не докажем их опасность. Собственно, сегодня я расскажу, как эксплуатировать cookie-based XSS уязвимости, а также приведу пример из тестирования одной компании, от которой я получил $7300 в целом за исследование.
⠀Для того, чтобы выполнить javascript на стороне пользователя, необходимо найти способ установки cookie и, если потребуется, заманить жертву на страницу, где, в свою очередь, внедряется кука. Возможные способы эксплуатации данного бага:
⠀1. CRLF injection. Данная уязвимость возникает, когда отсутствует надлежащая проверка и блокировка символов переноса строки. Мы можем внедрить хедер Set-cookie в ответ с желаемым названием, а также значением куки и установить её в браузере. Пример из реальной жизни: Скользкая CRLF injection на домене twitter.com в редиректе, — https://twitter.com/login? redirect_after_login=/jjjkkk嘊嘍Set-Cookie: jjjjj=a; domain=twitter.com

⠀Репорты о данном типе уязвимости можно почитать на HackerOne Репорты о данном типе уязвимости можно почитать на HackerOne https://hackerone.com/hacktivity? order_direction=DESC&order_field=popular&filter=type%3Apublic&querystring=crlf%20injection…
⠀2. XSS уязвимость на поддомене. Необходимо, чтобы XSS была общедоступна и находилась на wildcard *.vulnerabledomain.com. Для многих bug bounty программ поддомены — это out of scope, тоесть в большинстве случаев баги либо вообще не принимают, либо же принимают с пометкой «not eligible for the bounty». В таких случаях отступать не следует, но ради связки с cookie-based XSS можно инвестировать своё время на поиск XSS, чтобы получить вознаграждение. Если XSS обнаружена, мы можем устанавливать или удалять куку с помощью document.cookie функции.
Повышение импакта: Зачастую жертва доверяет главному домену vulnerabledomain.com больше, чем, например, jira.vulnerabledomain.com, да ещё и с URL /plugins/servlet/oauth/users/icon-uri? consumerUri=https://maliciousdomain.com. С большей вероятностью она перейдет на главный домен, нежели чем на поддомен, если этот поддомен не связан с личным кабинетом или авторизацией. Исходя из вышеизложенного, мы можем использовать in-site редирект функциональность для редиректа на поддомен vulnerabledomain.com/login? redirectUrl=https://jira.vulnerabledomain.com/path для лучшего эффекта.
⠀Если у жертвы есть активная сессия, редирект будет автоматическим, если нет,- нужна авторизация. Когда юзер кликнет по такой ссылке, кука будет установлена и с поддомена, на которой присутствует Reflected XSS его можно будет направить дальше по течению — на страницу с cookie-based XSS, где может сработать эксплойт, который, в свою очередь, схватит значение CSRF токена и выполнит запрос на смену email адреса. Таким образом, связка двух XSS уязвимостей может привести к account takeover, если не возникнет попутных проблем, таких как дополнительное подтверждение смены email паролем или кодом со старого ящика.
⠀3. Обнаружение тестовых файлов, которые позволяют устанавливать куки. Достаточно расчехлить тулзу обнаружения контента (dirb, dirserach, etc), начать копать и, если разработчики забыли выполнить очистку, то можно наткнуться на подобные файлы.
⠀Недавно я обнаружил тестовую servlet html страницу, на которой возможно было устанавливать куку с произвольным именем и значением. Защита на POST запросе, конечно же, отсуствовала, поэтому если жертва посетила бы CSRF эксплойт (или можно поменять POST на GET), появилась бы возможность установить куку в её браузере.

⠀Этот баг квалифицировали как недо-альтернативу CRLF injection, пофиксили удалением /examples/ и выплатили $150 как за low-severity bug. Хотя h1 triager поставил medium, разработчики все-таки склонились к тому, что это low severity.

⠀4. Man in the middle attack (MITM). Данный способ возможно применить только в случае отсутствия secure флага на cookie. Если вы не знаете, что это за флаг или просто хотите освежить память, советую просмотреть презентацию «Cookie security» с OWASP London 2017 www.owasp.org/images/a/a0/OWASPLondon20171130_Cookie_Security_Myths_Misconceptions_David_Johansson.pdf.
⠀Для успешной атаки необходимо, чтобы жертва находилась в сети атакующего или на резолвинг dns можно было бы повлиять. Для того, чтобы проверить уязвимость, необходимо:
1) захостить файл index.php со следующим содержимым:
⠀2) Добавить в ваш /etc/hosts/ файл следующую строку: 127.0.0.1 non-existed-subdomain.vulnerabledomain.com
⠀3) Посетить non-existed-subdomain.vulnerabledomain.com и после открыть страницу, на которой рефлектится кука.
⠀Замечательный пример MITM эксплуатации на e.mail.ru, — https://hackerone.com/reports/312548,- как можно заметить, MITM хватило для доказательства небольшой опасности уязвимости, но награда не соответствовала уровню Stored XSS, так как был показан только «локальный» способ эксплуатации, то есть не «in-the-wild». Если бы исследователь потратил немного времени на поиск XSS или CRLF injection (которых бесчисленное количество), находящихся на *.mail.ru, можно было бы несколько увеличить награду.
⠀Но далеко не все программы на hackerone принимают cookie-based XSS через MITM. Если в scope exclusions говорится «Self XSS», то данную эксплуатацию могут посчитать как Self XSS и выставить informative или n/a, что не всегда приятно. Сейчас я расскажу о подобном случае, который произошел со мной во время очередной охоты на платформе.
⠀Тестируя сайт, я внезапно увидел, что значение куки redacted отражается на одной из поддиректорий сайта. Первое, что я сделал — проверил отображение символов ' »/<>. Выяснилось, что фильтруются только символы <>, а это говорит нам о том, что мы не можем выйти за пределы , но так же становится понятно, что остальные символы не фильтруются. Долго не думая внедряем '-alert (document.domain)-' и js выполняется.
⠀Так как разработчики не наделили cookie флагом secure, в данном случае действует MITM способ. Было принято решение отправить репорт в программу cо следующим импактом:

⠀HackerOne staff (triager) дал четко понять, что это self-XSS и я должен try-harder:

⠀После этого я принялся бороздить просторы сайта и пытаться найти CRLF injection или XSS, чтобы доказать опасность.
⠀Пришлось расширить список поддоменов с помощью брута по большому словарю, скрапингу поддоменов с SSL сертификатов и с помощью некоторых других уловок. Результат не заставил себя долго ждать, так как большинство тулзов я запускаю c VPS. Время от времени попутно так же обнаруживались другие баги, которые я репортил, делая in-scope из out-of-scope, если нужно. Попадалось много Open Redirect-ов и даже Improper Access Control баг на $5000, но нужных уязвимостей для связки все никак не удавалось поймать. Выше упомянутый баг довольно интересный и опасный, целый поддомен увели в офлайн сразу после репорта, возможно, в будущем раскрою репорт на странице hackerone.com/w2w, если программа станет публичной.
⠀Спустя неделю были проверены результаты скрипта для обнаружения контента, где нашелся эндпоинт /verification, которому я сначала не придал особого значения, но все же натравил на него скрипт,- обнаружилась поддиректория /verification/login. После перехода показывалась страница /verification/login/? redirect_uri=https://vulnerabledomain.com, которая перенаправляла к значению redirect_uri после входа или сразу редиректила, если была сессия. После полета в интрудер обнаружился обход open redirect protection, — vulnerabledomain.com@anotherdomain.com. Попытался раскрутить баг до XSS — пейлоад javascript: alert (1) потерпел неудачу, javascript: alert (1)// тоже. А вот пейлоад javascript://https://vulnerablesite.com/%250A1? alert (1):0 выстрелил, потому что из-за присутствия vulnerablesite.com, параметр прошел white-list валидацию.

⠀После безумного вождения мышью по окну оповещения (всегда так делаю), я сразу же принялся за свою cookie-based XSS. С помощью javascript: https://vulnerabledomain.com/%0A1? document%2ecookie%20%3d%20%27SID%3d137gf6g67f76fg6766123%5c%27-alert%28document%2edomain%29-%5c%27%3b%20expires%3dFri%2c%203%20Aug%202019%2020%3a47%3a11%20UTC%3b%20path%3d%2f%3b%20domain%3d%2evulnerabledomain%2ecom%3b%27%3a0 кука успешно садилась на *.vulnerabledomain.com. После перехода на страницу с кукой вылетел заветный алерт! Double XSS, ура! :) Я дополнил репорт и стал ждать ответа.

⠀В этот же день прилетела «Nice catch» от триаджера (если можно это так назвать), и bounty была выплачена. Благослови Господи компании, которые платят на triage!
⠀За DOM based XSS, с помощью которой я устанавливал куку, тоже прилетела bounty.

⠀
Итоги тестирования:
$1000 + $1000 + $200 (OR)+ $100(OR) = $2300
⠀Данная программа функционирует уже больше года, но менее чем за месяц я смог занять в ней первое место и уйти с тестированием довольно далеко,- попытался пофазить большинство эндпойнтов, оценить их реакцию, понять, как работает сайт и даже тестировал desktop приложение. Эта баг баунти программа стала одной из самых любимых на HackerOne. Надеюсь и вы тоже когда-нибудь найдете ту самую! :)

Также, именно эта программа дала мне новый буст (mail.ru — первый), — с помощью него я добрался до 2500 репутации (привет hoodie) и попал на 36-е место в лидерборде по репутации за 90 дней, что должно дать свежие приватки. Хотя, кажется, приватки прилетают независимо от присутствия в лидерборде, я часто отменяю старые приватки и жду новые в очереди.
⠀
Краткий бриф:
— Cookie-based XSS вполне эксплуатирумые. Если постараться и копнуть немного глубже, то можно получить баунти вместо n/a, уничтожения сигнала и -5 к репутации.
— Если программа старая, это не значит, что в ней не будет уязвимостей. Если плоды долго висят на дереве, low-hanging фрукты сорвут и сразу же заберут домой (subdomain takeovers, др). Другие же фрукты продолжают висеть, но повыше. Для того, чтобы их достать, нужно приложить некоторые усилия.
— Иногда лучше сосредоточиться на одной программе на долгое время, найти максимально много уязвимостей и мониторить ее. Лучше найти ту программу, которая вам больше по душе и ломать её.
— Упорство и желание понять, как работает веб приложение, а так же те или иные функциональности и их взаимодействие между собой- это ключ для успешного поиска уязвимостей в баг баунти.
Если вы хотите быть в курсе моих последних статей и новостей, советую подписаться на телеграм канал / твиттер, ссылки на которые можно найти внизу.
