Client-Side DoS, или, ещё одна уязвимость, за которую вам не заплатят
В современном мире уже придумали так много всего, что мы можем использовать защитные механизмы против того, кто их внедрил
Привет Хабр!
В этой небольшой статье хочу поделиться кейсом, с которым я столкнулся на одном из проектов во время работы, а также моими мыслями на этот счёт.
Дисклеймер: в целях сохранения конфиденциальности, задействованная компания называться не будет, а скриншоты будут заменены альтернативными иллюстрациями (их у меня просто не осталось:))
А теперь, пожалуй, приступим.
С чего все началось
В один прекрасный день мне нужно было проверить воспроизводимость XSS в веб-приложении, которую ранее обнаружил другой исследователь. Никакого Rocket Science здесь не было — самая классическая Reflected XSS в параметре GET-запроса. Выглядело это примерно так: выполнялся переход по подобной ссылке:
https://example.com/?param=
Далее параметр встраивается в тело HTML-документа и мы могли видеть ожидаемый алерт:
Примерное проведение XSS атаки
Впрочем, ничего необычного тут не было — уязвимость подтвердили, успешно про неё забыли и ушли дальше заниматься своими пентестерскими делами.
Спустя день или два, при попытке посетить домашнюю страницу ресурса я получил вот такой вот ответ приложения:
Попытка посещения домашней страницы приложения спустя время
Тут сразу стало понятно, что меня начал блокировать WAF, однако выяснить причину такого поведения в моменте не удалось: объективных предпосылок на то не было — посещалась домашняя страница, без каких либо целей поиска и эксплуатации уязвимостей. Более того, делалось это через обычный браузер без проксирования трафика, поэтому детального анализа отправляемого пакета не производилось.
Со всеми этими грустными новостями я пошел разбираться к администраторам ресурса (один из таких в тот момент по счастливому стечению обстоятельств находился в доступности).
Раскрытие тайны
После изучения логов и сигнатур, по которым мое обращение к ресурсу было заблокировано, было обнаружено то, что, возможно, некоторые читатели данного поста уже поняли, исходя из написанного ранее — среди тонны cookie, которые отправил мой браузер при посещении ресурса была та, которая содержала в своем теле полезную нагрузку, отправленную мной пару дней назад: .
WAF это всё дело увидел и решил заблокировать мой запрос (что, в целом, логично поведению WAF). Разобравшись чуть больше в этом вопросе, я обнаружил, что помимо встраивания полезной нагрузки в HTML, приложение добавляло её в трекинговую cookie, как и последние несколько запросов, сделанных к ресурсу, что делало саму cookie огромной по длине и сложной для ручного анализа (а еще таких cookie было несколько).
Ну окей, мы разобрались с тем, как XSS-нагрузка попала в запрос. Но это породило еще больше вопросов — почему WAF начал блокировать запрос только спустя два дня и почему в таком случае не был заблокирован изначальный запрос с Reflected XSS?
Конкретно в нашем случае сошлись сразу два события:
WAF «моргал» в день проверки наличия первоначально найденной XSS, что помешало ему обнаружить и пресечь атаку
В следующие дни после первичной эксплуатации были обновлены правила детектирования WAF
Иными словами, схема кейса была следующая:
Схема кейса
В итоге, доступ легко восстановился через очистку всех cookie, все причастные разработчики и администраторы были уведомлены о проблемах, через время это все починили. Тем не менее, данная ситуация показала мне довольно необычный вектор, о котором я расскажу далее.
И что дальше?
Если мы уберем момент с эксплуатацией XSS, мы получим, что приложение «сохранило» нашу нагрузку, что обеспечило отсутствия доступа меня как посетителя веб-ресурса. Подобно бомбе замедленного действия, она терпеливо ждала своего часа. Cookie, в особенности трекинговые, могут жить очень долго — чуть ли не вечность, что в данном случае может обеспечить длительную недоступность ресурса для пользователя. Да, решить проблему можно легко — сделав очистку браузера. Тем не менее, рядовому пользователю интернета такой путь может быть не знаком и более того — до него еще нужно додуматься: если ты просто посещаешь сайт и видишь такое окно, происходящее и возможные варианты действий становятся неочевидными.
Данную атаку можно классифицировать как Client-Side DoS — происходит ограничение доступности к ресурсу, связанное с проблемой только на стороне клиента. При этом, вовсе не обязательно, чтобы что-то эксплуатировалось — достаточно только чтобы WAF считал ваш запрос подозрительным. Поразмыслив некоторое время над тем, как можно добиться реализации этой атаки, я пришел к данным вариантам:
Можно надеяться на удачу, как это было в моем случае. WAF имеет свойство периодически «моргать», особенно, если инфраструктура компании не обладает должной стабильностью. В этом случае все просто, но долго — нужно выждать момент, когда WAF не будет работать и отослать нагрузку жертве. Когда WAF снова заработает, доступ у жертвы пропадёт. Выглядеть это будет примерно так:
Схема первого варианта реализации атаки
Тот же метод будет работать, если для конкретного приложения найти способ временно отключить или заDoSить сам WAF.
Использовать патчевание и обход WAF. Время от времени в решениях класса WAF находят способы обхода, что способствует выпуску новых версий ПО и правил. Очевидно, что компаниям нужно некоторое время, чтобы изменения вступили в силу. В таком случае, жертве может направляться запрос, содержащий полезную нагрузку, которая не блокируется текущей версией WAF, но будет заблокирована в новой. Данный способ уже постабильнее предыдущего, но в нем надо действовать быстро. Вот как это может работать:
Схема второго варианта реализации атаки
Использовать способы назначения cookie. Данный способ показался мне наиболее интересным, так как он уже не завязан на особенностях cookie, используемых приложением. Сделать это можно, например, обнаружив XSS на одном из поддоменов целевого ресурса. Благодаря правильному выставлению атрибута Domain мы можем устанавливать cookie с поддомена на основной домен, согласно спецификации (в обратную сторону это, к слову, не работает). Мы также можем встретить ситуации, когда основной домен стоит за WAF, а поддомен — нет. Причин этому может быть много — про него забыли, не посчитали нужным помещать за WAF, не денег и т д. Тем не менее, эксплуатировав XSS на поддомене, мы можем поставить любую куку, которую будет считать подозрительным WAF на основной домен и тогда при его посещении у жертвы будет отсутствовать доступ к системе.
Вот как это может выглядеть:Схема третьего варианта реализации атаки
К сожалению, ввиду довольно иллюзорного влияния уязвимости, нахождение такой самой по себе вряд ли принесет вам больших денег на BugBounty (если вообще принесёт). Тем не менее, ее можно вполне использовать как доказательство влияния какой-то другой уязвимости (например, XSS).
Спасибо, за прочтение! Хороших вам уязвимостей и чтобы за них платили!