May 17, 2023

Ищем XSS как профессионалы. Часть 1

🥷 Приветствую друзья


Содержание:

  1. Что такое XSS?
  2. Методология поиска XSS
  3. Какую проверочную строку (пейлоад) использовать

Прежде чем перейти к примерам XSS, вспомним, что такое XSS?

XSS (Cross Site Scripting) - простыми словами это возможность выполнения произвольного javascript-кода в браузере жертвы в контексте вашего сайта

И вспомним, как вызывается javascript из html-страниц, например:

<javascript>...</script> 

В данном случае всё что находится внутри тега <script> выполнится как javascript.

Также можно использовать обработчики событий, то есть соответствующий атрибут, например, onerror:

<img onerror="..." src="x">test</a>

В данном случае браузер попробует подгрузить картинку по источнику х, и если картинка не загрузится браузер выполнит то что указано в обработчике событий.

Также про атрибуты стоит добавить, что есть еще всякие гиперссылки, src-атрибуты. И в случае с гиперссылкой интересно то что если гиперссылка ведет не на схему http или https, т.е. не относительная, а начинается со схемы javascript то при ее нажатии, всё что после схемы javascript будет рендерится как javascript, например:

<a href="javascript:...">click to trigger javascript</a>

Тоже самое работает с iframe:

<iframe src="javascript:..">

Стоит также добавить, что XSS самая распространенная уязвимость в вебе, и чтобы ее найти не нужно обладать особыми навыками, но при этом она остается одной из серьезных клиентских уязвимостей, и за неё хорошо платят на багбаунти :)

Разберемся с причинами появления данной уязвимости.

  1. Во первых она возникает при генерации html-страницы когда разработчику нужно показать какие-то данные на странице, какие-то пользовательские данные засунуть в html-страницу, например пользователь ввел свое имя и разработчику нужно отобразить это на странице браузера, и в случае когда разработчик что-то записывает от пользователя в базу данных и затем тянет это в шаблон, называют - Stored XSS
  2. Также разработчику может потребоваться брать параметры из url или из тела запроса, такой тип - Reflected XSS
  3. На самом деле это не все причины появления уязвимости, например еще могут быть динамические изменения страницы javascript'ом, есть всякие события которые происходят на клиентской стороне, но здесь мы коснемся двух основных уязвимостей

Возьмем пример

Обычная страница Вконтакте. О чем подумает человек который хочет найти XSS? Во первых он обратит внимание что есть поле, можно ввести телефон или эмайл, попробуем ввести туда честные данные и пейлоад для XSS

Что произойдет в данном случае?
Мы как пользователь который хочет зарегистрироваться заливаем на сайт свои данные, разработчик записывает эти данные и ему нужно отобразить пользователю эти данные на страницах сайта (например на главной странице профиля). И если разработчик не подумал что в качестве имени пользователя могут быть не только валидные данные, а еще и html теги, то они встроятся в оригинальный html шаблон и так как браузер рендерит всё что ему укажет разработчик всё что будет внутри тега script исполнится как javascript.

Но конечно, такой уязвимости там нет, это теоретический пример.


Метод который я опишу далее идеально подходит для поиска XSS в формате Black Box

Методология:

1. Пейлоад во все поля/параметры

Мы пихаем пейлоад для проверки XSS, во все поля которые можем найти

2. Смотрим в DOM на предмет санитизации

3. Рано или поздно какие-то спец-символы не перекодируются/функция alert выполнится

4. Раскручиваем или репортим

Например, есть страничка поиска с полем для ввода, попробуем ввести туда qweqwe

Поищем это в DOM - F12 - Ctrl + F - 'qweqwe'

Мы видим то что наша строка qweqwe из поля для поиска попала в параметр q и также она попала на страницу 9 раз, то есть у нас есть 9 мест на странице где разработчик мог не добавить защиту от данной уязвимости.

Но конечно для поиска XSS строки qweqwe недостаточно, добавим к ней спецсимволы:

qweqwe ' " < >

Сразу можно увидеть что спецсимволы санитизируются, но одно из попаданий на первый взгляд кажется успешным, спецсимволы на первый взгляд не перекодировались:

Попробуем посмотреть что там происходит в html

Здесь мы видим что спецсимволы превращаются в html entities, и это тоже кодировка, браузер активно ее использует, ее особенность в том что бразуер рисует соответствующий символ на странице в обычном виде, но записывается символ с помощью html entities.

Санитизация - преобразование определенных символов пользовательской строки в соответствующие html entities или другую кодировку.

В нашем примере есть санитизация, но что если бы ее не было?

Попробуем представить, вводим:

qweqwe ' " test

И попробуем найти это на странице:

Что мы видим?
Во первых мы видим что test подсвечивается коричневым, браузеры подсказывают что test в данном случае стал атрибутом.

Соответственно если мы вместо test будем использовать обработчик событий, например:

qweqwe ' " onfocus='alert()' autofocus

Мы получаем Reflected XSS


В данной статье я попробую предложить универсальный пейлоад, который поможет найти любую XSS.

XSS - Level 0

Самый простой вариант XSS:

<script>alert()</script>

Рассмотрим на примере PHP - когда мы как разработчик хотим выводить пользователю какой-то html-код и туда подтягивается значение параметра name. Функция echo в PHP не совершает санитизации и поэтому наш пейлоад будет рендерится как есть и скрипт выполнится

Тоже самое если разработчик берет параметр не из url, а ходит в базу данных и берет какие-то данные которые пользователь ему ввел до этого:

Абсолютно тоже самое, выполняется функция alert()

Рассмотрим пример посложнее, а что если мы попали внутрь значения атрибута?

Наш предыдущий вариант не сработает, потому что нужно закрыть атрибут, но мы закроем не только атрибут, мы также закроем и тег input и встроим свой script который отрендерится браузером:

В итоге раз мы знаем что бывают случаи когда мы можем попасть внутрь значения атрибута, почему бы сразу не добавить это в наш универсальный пейлоад?

XSS - Level 1

Идём дальше!

А если пользовательское значение подставляется внутрь тега title?

Сработает ли наш текущий пейлоад?

Нет, потому что тег title нужен браузеру для того чтобы отображать имя вкладки, браузер не рендерит его как html. Тут будет достаточно изменить наш пейлоад на:

Таким образом мы закрыли оригинальный title и можем продолжать.

Раз мы уже знаем что разработчик может подтянуть наше значение внутрь тега title почему бы сразу не добавить этот случай в наш пейлоад и детектить сразу многие случаи?

"></title><script>alert()</script>

А вот если мы попали внутрь тега script? То есть разработчик написал какой-то javascript, внедрил у себя его на странице, но какую-то переменную берет из пользовательского ввода:

Наш пейлоад снова не подходит, но здесь снова всё тривиально, и добавляем к итоговому варианту закрывающий тег </script>

Нет смысла показывать каждый такой тег, приведу их в пример

"></title></script><script>alert()</script>
+ </style></noscript></textarea> и тому подобное

🔥 На сегодня все, продолжим в следующей части

Во второй части разберём:

• Реальные кейсы с bug bounty программ

• Какие баги можно найти

⚡️ Поставь реакцию под постом

❓ Остались вопросы? - @golden_hpa