Physical Address
304 North Cardinal St.
Dorchester Center, MA 02124
Physical Address
304 North Cardinal St.
Dorchester Center, MA 02124
Недавно я обнаружил новую для себя разновидность XSS-уязвимостей — DOM XSS с помощью Web Messaging. Перечитав множество страниц документации, я решил создать единый материал по эксплуатации XSS через эту технологию. Я опишу здесь наиболее распространенные недостатки безопасности и методы их эксплуатации.
DOM (Document Object Model) — не зависящий от платформы и языка программный интерфейс, который позволяет программам и скриптам получать доступ к содержимому HTML-, XHTML-, XML-документов, а также изменять их контент (содержимое, структуру, оформление). DOM-based-уязвимости возникают, когда веб‑сайт содержит сценарий, который принимает контролируемое злоумышленником значение и передает его небезопасной функции, называемой sink. Один из видов DOM-based-уязвимостей — DOM-based XSS. Уязвимости этого типа возникают, когда JavaScript получает данные от пользователя и передает их в sink, обладающий возможностью динамического исполнения кода, например eval()
, document.write()
или innerHTML
.
Наиболее популярный источник DOM XSS — URL-страницы. Доступ к этому значению осуществляется с помощью JavaScript через объект window.location
. Затем URL обрабатывается внутри существующего на странице легитимного скрипта. В этом случае атакующий может создать ссылку с вредоносной нагрузкой, чтобы затем отправить ее жертве. Когда жертва перейдет по ссылке, исходный скрипт на странице, использующий объект window.location
, запросит адрес текущей страницы и исполнит нагрузку, которая содержится в URL. Вот простейший пример этой уязвимости.
<body><script>document.write(location.href);</script></body>
При получении такой страницы браузер автоматически выполнит скрипт и запишет в тело страницы (document.write
) строку, взяв ее значение из location.href
(полного адреса страницы). Однако пользователь контролирует значение location.href
и может поместить в него произвольную строку. Поэтому для эксплуатации XSS-уязвимости достаточно сформировать следующую ссылку, и при ее открытии в браузере выполнится вредоносный скрипт.
http://website.com/index.html#<script>alert(1)</script>
Представим, что у нас есть страница сайта, который мы разработали. Мы помещаем на нее элемент <iframe>
и указываем в качестве его источника произвольный сайт.
Принципиальная схема iframe
Если бы не было механизмов безопасности, обмен данными между элементами родительской веб‑страницы и веб‑страницы, отображаемой в <iframe>
, мог бы быть критически опасным для пользовательских данных. Любой скрипт, находящийся на родительской странице, мог бы получить доступ к любым данным, размещенным внутри <iframe>
.
Рассмотрим на примере: злоумышленник помещает на своей странице <iframe>
с адресом интернет‑банка, в котором пользователь был авторизован ранее. Затем каким‑то образом заманивает жертву на свою страницу. В результате злоумышленник может получить доступ к любым пользовательским данным личного кабинета интернет‑банка жертвы. Чтобы не допустить подобного, были созданы два механизма защиты:
Same Origin Policy (SOP), «политика одинакового источника», — предотвращает кросс‑доменные атаки, блокируя чтение загружаемых ресурсов из другого источника. Источник идентифицируется по следующей тройке параметров: схема, полное имя хоста и порт. Когда хотя бы один из параметров между источниками не совпадает, обмен данными между ресурсами запрещается. Например, если страница по адресу http://example.com/index.html
попробует отобразить данные из источника https://example.com/
, то это действие будет запрещено, так как у источников не совпадает протокол.
Same Origin Policy
Cross-Origin Resource Sharing. Ограничения политики одинаковых источников оказались слишком жесткими. Поэтому для более тонкой настройки доступа к ресурсам создали «механизм совместного использования ресурсов разными источниками» — CORS. Он регламентирует три категории сетевого взаимодействия:
<link>
, <script>
, <img>
, <video>
, <audio>
, <iframe>
и других. По умолчанию все они разрешены, однако работоспособность тега <iframe>
может быть дополнительно ограничена с помощью заголовка X-Frame-Options
;
www
Подробнее о CORS и SOP ты можешь прочитать, к примеру, в этих статьях на «Хабрахабре»: «CORS для чайников: история возникновения, как устроен и оптимальные методы работы» и «Политика общего происхождения и CORS: визуальное руководство».
Window.postMessage()
— это метод, позволяющий передавать данные между документами, которые загружены в разных окнах или фреймах, в том числе между документами, полученными с разных доменов. Если на сайте корректно настроены механизмы безопасности (SOP и CORS), использование postMessage
будет единственным доступным способом передачи данных между документами на разных доменах. Запросы, созданные с помощью прочих методов (как, например, XMLHttpRequest
или Fetch API) будут заблокированы в соответствии с SOP и CORS.
Поиск информации о технологии postMessages привел меня к официальной документации Mozilla. Обычно сценариям из разных источников разрешен доступ друг к другу тогда и только тогда, когда они соответствуют Same Origin Policy (одинаковая схема, имя хоста и порт), включая сценарии внутри фрейма, которые обращаются к родителю фрейма. Window.postMessage()
предоставляет контролируемый механизм для безопасного обхода этого ограничения. Также я нашел в документации способы обеспечения связи между родительской страницей и страницей внутри фрейма. В общем виде дочерний <iframe>
должен быть подписан на событие «сообщение»:
window.addEventListener("message", (event) => {...}, false);
Здесь message
— ожидаемое сообщение.
В таком случае родительская страница может передать дочернему фрейму сообщение с помощью такого метода:
postMessage(message, targetOrigin, transfer)
Здесь message
— отправляемое сообщение, эти данные автоматически сериализуются для передачи в дочерний фрейм, а targetOrigin
указывает источник родительского окна.
В качестве targetOrigin
допускается использовать звездочку, которая указывает на то, что получить сообщение может кто угодно. Либо можно указать конкретный URI, который будет проверен внутри слушателя в дочернем фрейме. Если Origin страницы не совпадает с targetOrigin
внутри этой функции, событие не будет отправлено. Этот механизм обеспечивает контроль над тем, куда отправляются сообщения. Например, если postMessage
используется для отправки пароля, необходимо, чтобы этот аргумент соответствовал целевому URI. Это позволит предотвратить хищение пароля злоумышленником через недоверенный ресурс.
Давай посмотрим, как можно использовать веб‑сообщения в качестве источника для создания и эксплуатации DOM XSS на целевой странице. Если целевая страница обрабатывает входящие сообщения небезопасным образом (например, неверно проверяя источник входящих сообщений), то вызываемые слушателем события потенциально могут стать приемниками небезопасной нагрузки и источником XSS.
Например, злоумышленник может поместить на своей странице вредоносный <iframe>
и использовать метод postMessage()
для передачи данных с помощью веб‑сообщения уязвимому слушателю событий. В дальнейшем слушатель передаст вредоносную нагрузку в приемник на дочерней странице.
Это значит, что веб‑сообщения могут быть использованы в качестве источника нагрузки для любого из приемников дочерней веб‑страницы. Результат эксплуатации уязвимости зависит от того, как целевой документ обрабатывает полученные сообщения.
Если целевая страница полностью доверяет отправителю, не проверяет данные, полученные от него, и без искажений передает их в приемник, то эта уязвимость позволит злоумышленнику совершить любые действия от лица пользователя в контексте целевого ресурса (скомпрометировать пользователя).
Давай рассмотрим разные варианты уязвимого кода.
Источник: xakep.ru