• XSS.stack #1 – первый литературный журнал от юзеров форума

Статья Осваиваем DOM Invader: ищем DOM XSS и Prototype Pollution

tabac

CPU register
Пользователь
Регистрация
30.09.2018
Сообщения
1 610
Решения
1
Реакции
3 333
Сегодня мы познакомимся с DOM XSS и Prototype Pollution, рассмотрим примеры уязвимостей на Bug Bounty и научимся использовать инструмент DOM Invader, который заметно упростит поиск таких уязвимостей.

XSS
Межсайтовый скриптинг, известный как XSS, часто встречается в мире веб-безопасности. Наряду с IDOR он занимает первые места в рейтинге Bug Bounty по количеству найденных уязвимостей. Атака позволяет внедрить JavaScript-код на страницу приложения, после чего пользователи, посещающие уязвимую страницу, могут потерять различные конфиденциальные данные — например, сеансовые куки или токены авторизации.

Document Object Model (DOM)
Document Object Model (DOM) — это иерархическое представление элементов на странице в веб-браузере. Сайты могут использовать JavaScript для управления узлами и объектами DOM. Манипуляции с DOM сами по себе не являются проблемой — так работают все современные сайты. А вот JavaScript, который небезопасно обрабатывает данные, может позволить провести различные атаки. Уязвимости DOM возникают, когда на сайте содержится JavaScript, который берет значение, контролируемое пользователем (Source), и передает его в опасную функцию (Sink).

Source
Свойство JavaScript, которое принимает данные, потенциально контролируемые пользователем. Пример источника — свойство location.search, поскольку оно считывает ввод из строки запроса, которой относительно просто управлять. В конечном итоге любое свойство, которым может управлять пользователь, является потенциальным Source. К этому относятся URL-адрес источника (document.referrer), Cookie пользователя (document.cookie) и WebMessages (подробнее про WebMessages написано здесь).

Sink
Потенциально опасная функция JavaScript или объект DOM, которые могут вызвать уязвимость, если в них передаются данные, контролируемые пользователем. Например, функция eval() является Sink'ом, поскольку она обрабатывает аргумент, который в него передается, как JavaScript. Примером HTML-Sink является document.body.innerHTML, так как это потенциально позволяет внедрить HTML и выполнить произвольный JavaScript.

Gadget
Небольшие фрагменты кода, которые могут быть использованы для эксплуатации уязвимостей. «Гаджеты» часто применяются в цепочках уязвимостей для достижения более значительного импакта. Еще их используют для обхода защитных мер, повышения привилегий или выполнения произвольного кода.

DOM Invader
DOM Invader — это браузерный инструмент, который поможет в поиске уязвимостей DOM XSS, Prototype Pollution и DOM Clobbering. Суть его функции — в изучении различных Sources и Sinks, включая векторы postMessage. Он доступен через встроенный браузер Burp Suite: это уже предустановленное расширение, его нужно просто включить в настройках.
7956e14eca453f3b4659316ec7b662a7.png

Что умеет DOM Invader?
  1. Проверять на DOM XSS. Расширенное представление DOM позволяет мгновенно определить управляемые Sinks на странице, показывая вам точку внедрения и XSS-контекст, и то, как обрабатывается переданный ввод.
  2. Логировать, изменять и повторно отправлять WebMessage с помощью метода postMessage(). Это позволяет тестировать DOM XSS через WebMessage (подробнее).
  3. Автоматически определять Sources Prototype Pollution на стороне клиента и сканировать управляемые Gadgets, которые передаются в опасные Sinks.
  4. Автоматически выявлять уязвимости DOM clobbering (подробнее).
Прежде чем начать использовать инструмент, важно вспомнить сам контекст возникновения уязвимостей DOM XSS, так что нам пригодится немного практики.

Подготовка​

1. Обновите Canary (ключевое слово, используемое для идентификации уязвимости), в нашем случае это XXS.
4eb8805466db64cf02d8b5fb1056fda8.png


2. Откройте вкладку DOM Invader в инструментах разработчика (F12).

bc8b50ee01d4727f7c70fe9bda816e84.png


3. Откройте сайт, который будете проверять на уязвимости, и внедрите Canary в параметры.

cf9835599350c13a9b007ac5e3568768.png


4. На вкладке DOM Invader проверьте, возвращается ли Canary в Sink.

555b00afcabe1d2e59f52b1cc5c5e7b6.png


5. При необходимости проверьте Stack Trace. Он отображается в консоли при нажатии на соответствующую кнопку в DOM Invader.

4ad72d036562f9109954342b1114c372.png

А теперь перейдем к практике и разберемся с работой расширения на примере некоторых лабораторных Академии PortSwigger.

Лабораторная 1. DOM XSS in document.write sink using source location.search​

Здесь мы можем использовать функцию Inject forms, а затем нажать «Поиск» на странице сайта:
2b4b81e10307cb010a51fef7b828c5ea.png


В расширении можно будет увидеть, что Sink найден. Теперь можно пробовать проэксплуатировать уязвимость:

c8e2b7d90d865fada9cab088e32fd4de.png

Чтобы изучить эту точку внедрения подробнее, мы можем открыть Stack Trace, после чего получим уведомление о том, что трассировка доступна в консоли:

a95c7091b66fc610dc20c75b46d8501f.png

Теперь переходим в консоль и открываем кусок кода, в котором обнаружен Sink:

3ff91c7fb5f317aa0046b45a2ba28d12.png

Код:
<script>
function trackSearch(query) {document.write('<img src="/resources/images/track
}
var query = (new URLSearchParams(window.location.search)).get('search');
if(query) {
trackSearch(query);
}
</script>
Сначала мы создаем переменную query и добавляем в нее значение параметра search:
Код:
var query = (new URLSearchParams(window.location.search)).get('search');
Если query не null, мы вызываем функцию trackSearch и передаем в нее значение:
Код:
if(query) {
trackSearch(query);
}
Для записи строк на страницу используется функция document.write(). Сначала загружается страница, а затем на нее добавляется наше значение query:
Код:
document.write('<img src="/resources/images/tracker.gif?searchTerms='+query+'">')
В данном случае Source, или точка внедрения, — это значение location.search, которое мы контролируем, а Sink'ом является document.write.

Теперь переходим в DOM Invader и пробуем использовать кнопку Exploit — быть может, полезная нагрузка, подобранная расширением, сработает?
fc87c490ac96f21c8585bb573304ddff.png


Эксплойт не сработал, но можно заметить, что мы добавили на страницу "> и застряли в HTML-теге:

ff2238d1b1b2d2ca3c916e9191c6f7c5.png


Пробуем воспользоваться полезной нагрузкой, которая отобразилась на странице, и добавляем значение, которое отобразилось вне тега с результатом поиска:
Код:
“><img src=x onerror=alert(1)>

9bb2faa3ebdc5a82ffc2c5a002c43e6a.png

Хоть DOM Invader и не подсказал нам точный способ эксплуатации, данный инструмент помогает в поиске Sources, которые впоследствии можно эксплуатировать вручную.

Это довольно простой пример, и такую XSS можно найти вручную. Но когда мы тестируем приложение с огромным количеством форм, ручной анализ займет много времени, а DOM Invader ускорит нашу работу. В таком формате тестирование становится эффективнее. Нам больше не нужно тратить часы на изучение функций, источников и тому подобного, чтобы найти XSS.

Лабораторная 2. DOM XSS in innerHTML sink using source location.search​

Переходим в DOM Invader, жмем inject forms, после нажимаем поиск на странице:
da5cd97927d6131cbf4ee7d7959d29db.png


Смотрим Stack Trace:

c5b27660ea7a07a86284b64136f19a77.png

Код:
document.getElementById('searchMessage').innerHTML = query;
Эта строка вставляет наши входные данные в элемент HTML с идентификатором “searchMessage”. Здесь используется метод .innerHTML, что создает потенциальную уязвимость, так как он вставляет небезопасные данные напрямую в элемент.

Жмем Exploit в DOM Invader и видим, что в результате вывелось оповещение и JavaScript выполнился:

5346598eb3f547684d5cae51efaf2540.png

Лабораторная 3. DOM XSS in document.write sink using source location.search inside a select element​

В данной лабораторной немного меняются точка внедрения и логика приложения, поэтому, чтобы найти точку внедрения, необходимо проверить функцию проверки остатков товара:
d2f15e3e8258685086ce00f8c9234f3e.png


Посмотрев запрос, находим параметр storeId в функции проверки остатков товара:

dd487bd952eaefc6828b14f0a0d5cae2.png


Передаем параметр storeId в GET-запросе и запускаем DOM Invader, жмем Inject URL params:

fb5edcce8154cc0d39e5df667b989a72.png


Смотрим код, в котором возникает уязвимость.

dc62dffa67d0dfcb12fbef9b9bf451ee.png

В этом фрагменте кода сначала присваивается значение переменной store параметра storeId из URL страницы:
Код:
var store = (new URLSearchParams(window.location.search)).get('storeId');
Значение 'storeId' не проверяется и попадает на страницу без обратки.
Код:
document.write('<select name="storeId">"'></select><img src onerror=alert(1)>');
Данная строчка кода отвечает за создание элемента выпадающего списка, и небезопасная функция document.write() создает уязвимость.
Код:
if(store)
{
document.write('<option selected>'+store+'</option>');
}
Существует условие: если для store задано значение, оно добавляется в список и отмечается как выбранное. Здесь и возникает уязвимость DOM XSS, так как значение store не проходит должной обработки.

Жмем Exploit и видим, что XSS не сработала и наш ввод попал между тегов option:

c296c79279dff792639318972a008d4d.png

Чтобы уязвимость сработала, возвращаемся к коду, смотрим на уязвимую функцию и немного изменяем эксплойт, чтобы закрыть тег select. Наша полезная нагрузка попадет в Sink примерно так:
Код:
document.write('<select name="storeId">'</select><img src onerror=alert(1)>');
Жмем Exploit в DOM Invader и видим, что в результате вывелось оповещение:

aff154ef065d5c569f467a849c769ab3.png

Лабораторная 4. DOM XSS via client-side prototype pollution​

Теперь мы ищем Prototype Pollution, и нам необходимо включить режим для поиска этой уязвимости в расширении.

5b02a4472477fe9c71d5cc19cfa98f04.png


Переходим на главную страницу и открываем расширение. Оно сразу обнаружило уязвимость:

ee617dab5ca2c5cc1c909216f414ec03.png


Жмем Scan Gadgets и видим найденный Sink:

5319fe90f9eae54faecf16e339d98bf7.png


Смотрим Stack Trace в консоли браузера и переходим к коду, где возникает уязвимость:

80393230a1eff72c9a779b5720c7eef8.png

Уязвимая часть кода:
Код:
if(config.transport_url) {
let script = document.createElement('script');
script.src = config.transport_url;
document.body.appendChild(script);
}
В этом участке кода перед использованием config.transport_url не проверяется его источник. В результате, добавив proto[transport_url]=data:,alert(1) в запрос, можно заставить каждый объект, прошедший через deparam, получать свойство transport_url со значением data:,alert(1). Это значение будет использоваться как источник для нового элемента script, что приведет к выполнению кода alert(1).

Нажимаем Exploit:

c8479e2dbc59708246b206df878a9930.png

Лабораторная 5. Client-side prototype pollution via browser APIs​

Переходим в DOM Invader, где можно увидеть, что найдено две точки внедрения:

1e4a86f738157071e95a2f57ff287ad4.png


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

7d106e28ebe0e0aa9daf224db81e55c9.png


Теперь у нас есть источник и точка внедрения, переходим в DOM Invader, смотрим Stack Trace и уязвимый код:

b1e82105ba489855bf4ac7f88742f2de.png


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

250c4d35044f7930eaec728b0710be28.png

Bug Bounty. DOM XSS in Habr.com​

Можно подумать, что расширение поможет только при поиске простых XSS в лабораторных и не особо применимо на Bug Bounty или в новом проекте, но мой опыт показывает, что DOM Invader способен находить уязвимость где угодно.

Поскольку я публикую текст на Habr.com, я решил протестировать его на уязвимость и доказать вам тезис об универсальности DOM Invader.

Detect

Добавляем # на страницу и нашу канарейку после якоря, смотрим вкладку DOM Invader:

8d2655786595ca2ff2e8b6304e075291.png


Жмем Exploit:

6c476c2cc46dbddc3b458014b29f4d8b.png

Impact

Начнем с того, что мы можем реализовать перенаправление пользователя с помощью простой полезной нагрузки.
Код:
#'><img src onerror=eval(atob("ZG9jdW1lbnQubG9jYXRpb249aHR0cHM6Ly9ldmlsLmNvbQo="))>
Где ZG9jdW1lbnQubG9jYXRpb249aHR0cHM6Ly9ldmlsLmNvbQo=это:
Код:
document.location=https://evil.com

Хм, а чем это опасно?
  • Кража email
Перенаправление — это самый простой вектор атаки, и он может сыграть важную роль в эксплуатации данной уязвимости.

Для того чтобы увеличить импакт от уязвимости, я определил критичные пользовательские данные на Habr и заметил, что email авторизованного пользователя лежит в ответе от страницы. Оставалось только захватить данный элемент. Чтобы это сделать, я написал небольшой скрипт, который будет искать на странице элемент email с помощью регулярного выражения и отправлять его нам на сервер.

В результате мне удалось добиться кражи email авторизованного пользователя:

fd81807dde1049b26b0bb62c6ae918f0.png

  • Phishing XSS
В качестве эксперимента я реализовал фишинговый вектор атаки с отрисовкой формы логина в аккаунт, полезная нагрузка помещается в eval:

034f8db58421980bd4a173caeb0f7fd9.png

Внимательный читатель может сказать, что размер полезной нагрузки может быть достаточно большим, чтобы передавать его пользователю, на что я напомню про перенаправление, которое может помочь при эксплуатации уязвимости. Таким образом, пользователю нужно будет передать страницу с перенаправлением на уязвимый сайт, который после отправит его обратно на Habr, добавив якорь с полезной нагрузкой :) О найденной уязвимости я сообщил команде Habr, они отреагировали в течение одного часа, после чего уязвимость была успешно устранена, а я получил свое Bounty. Отдельное спасибо за быструю реакцию и разрешение упомянуть уязвимость в статье!

Полезные статьи в заключение​

Мы познакомились подробнее с природой уязвимостей DOM XSS и Prototype Pollution, узнали, как пользоваться DOM Invader и для чего он нужен. Надеюсь, статья была для вас полезной, и советую дополнительно почитать вот такие материалы:

Автор @wr3dmast3r
habr.com
 


Напишите ответ...
  • Вставить:
Прикрепить файлы
Верх