DOM-based
В этом разделе вы узнаете, что такое DOM и как небезопасная обработка данных DOM может приводить к уязвимостям. Также рассмотрим способы предотвратить уязвимости на основе DOM.
Лабораторные работы
Если вы уже знакомы с базовыми концепциями уязвимостей на основе DOM и просто хотите попрактиковаться в их эксплуатации на реалистичных, намеренно уязвимых целях, вы можете получить доступ ко всем лабораторным работам по этой теме по ссылке ниже.
Что такое DOM?
Document Object Model — это иерархическое представление элементов на странице браузером. Веб‑сайты могут использовать JavaScript для манипуляции узлами и объектами DOM, а также их свойствами. Манипулирование DOM само по себе не является проблемой. На самом деле это неотъемлемая часть работы современных веб‑сайтов. Однако JavaScript, который небезопасно обрабатывает данные, может открывать путь для различных атак. Уязвимости на основе DOM возникают, когда на сайте есть JavaScript, который принимает контролируемое злоумышленником значение, известное как source, и передаёт его в опасную функцию, известную как sink.
Уязвимости taint-flow
Многие уязвимости на основе DOM можно проследить до проблем с тем, как клиентский код манипулирует данными, контролируемыми атакующим.
Что такое taint-flow?
Чтобы эксплуатировать или предотвращать эти уязвимости, важно сначала ознакомиться с основами потока помеченных данных между источниками и приёмниками.
Sources
Source (или источник) — это свойство JavaScript, которое принимает потенциально контролируемые атакующим данные. Примером источника является свойство location.search, поскольку оно читает ввод из строки запроса, которую относительно просто контролировать атакующему. В конечном счёте, любое свойство, которое может быть контролируемо атакующим, является потенциальным источником. Это включает в URL-адрес источника запроса (доступен через строку document.referrer), пользовательские cookie (доступны через строку document.cookie) и веб‑сообщения.
Sinks
Sink (или приёмник) — это потенциально опасная функция JavaScript или объект DOM, который может вызвать нежелательные эффекты, если ему передать данные, контролируемые атакующим. Например, функция eval() является приёмником, поскольку она обрабатывает переданный ей аргумент как JavaScript. Примером HTML sink'а является document.body.innerHTML, поскольку он потенциально позволяет злоумышленнику внедрить вредоносный HTML и выполнить произвольный JavaScript.
По сути, уязвимости на основе DOM возникают, когда сайт передаёт данные из source в sink, который затем небезопасно обрабатывает эти данные в контексте клиентской сессии.
Наиболее распространённым источником является URL, к которому обычно обращаются через объект location. Атакующий может сконструировать ссылку, чтобы отправить жертву на уязвимую страницу с полезной нагрузкой в строке запроса и фрагменте URL.
Рассмотрим следующий код:
Этот код уязвим к open redirection на основе DOM, поскольку source location.hash обрабатывается небезопасно. Если URL содержит хеш-фрагмент, который начинается с https:, этот код извлекает значение свойства location.hash и устанавливает его в качестве значения свойства location окна. Злоумышленник мог бы эксплуатировать эту уязвимость, сконструировав следующий URL:
Когда жертва перейдет по этой ссылке, JavaScript установит значение свойства location на https://www.evil-user.net, что автоматически перенаправляет жертву на вредоносный сайт. Такое поведение легко может быть использовано, например, для фишинговой атаки.
Распространенные источники
Ниже приведены типичные источники, которые могут быть использованы для эксплуатации различных уязвимостей, основанных на taint-flow:
Следующие виды данных также могут использоваться как источники для эксплуатации уязвимостей, основанных на taint-flow:
Какие приемники могут привести к уязвимостям на основе DOM?
Следующий список даёт краткий обзор распространённых уязвимостей на основе DOM и пример приёмника, который может приводить к каждой из них. Для более полного списка соответствующих приёмников обратитесь к страницам, посвящённым конкретным уязвимостям.
document.write()
window.location
document.cookie
eval()
document.domain
WebSocket()
element.src
postMessage()
setRequestHeader()
FileReader.readAsText()
ExecuteSql()
sessionStorage.setItem()
document.evaluate()
JSON.parse()
element.setAttribute()
RegExp()
Как предотвратить taint-flow уязвимости на основе DOM
Не существует единственного действия, которое полностью устранило бы угрозу атак на основе DOM. Однако наиболее эффективный способ избежать уязвимостей — не допускать, чтобы данные из какого‑либо ненадежного источника динамически изменяли значение, передаваемое в любой приёмник.
Если желаемая функциональность приложения делает такое поведение неизбежным, следует реализовать меры защиты в клиентском коде. Во многих случаях соответствующие данные можно валидировать на основе белого списка, разрешая только заведомо безопасный контент. В других случаях потребуется очистка или кодирование данных. Это может быть сложной задачей и, в зависимости от контекста, в который попадают данные, может включать комбинацию экранирования JavaScript, HTML‑кодирования и URL‑кодирования в правильной последовательности.
На страницах конкретных уязвимостей также перечислены меры, которые помогут их предотвратить.
DOM clobbering
DOM clobbering — это продвинутая техника, при которой вы внедряете HTML на страницу, чтобы манипулировать DOM и в конечном итоге изменить поведение JavaScript на сайте. Наиболее распространённая форма DOM clobbering использует элемент ссылки, чтобы перезаписать глобальную переменную, которую приложение использует небезопасным образом, например для генерации динамического URL сценария.
Last updated