DOM-based

В этом разделе вы узнаете, что такое 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 и пример приёмника, который может приводить к каждой из них. Для более полного списка соответствующих приёмников обратитесь к страницам, посвящённым конкретным уязвимостям.

Уязвимость на основе DOM
Пример приёмника

document.write()

window.location

document.cookie

FileReader.readAsText()

sessionStorage.setItem()

document.evaluate()

JSON.parse()

element.setAttribute()

Как предотвратить taint-flow уязвимости на основе DOM

Не существует единственного действия, которое полностью устранило бы угрозу атак на основе DOM. Однако наиболее эффективный способ избежать уязвимостей — не допускать, чтобы данные из какого‑либо ненадежного источника динамически изменяли значение, передаваемое в любой приёмник.

Если желаемая функциональность приложения делает такое поведение неизбежным, следует реализовать меры защиты в клиентском коде. Во многих случаях соответствующие данные можно валидировать на основе белого списка, разрешая только заведомо безопасный контент. В других случаях потребуется очистка или кодирование данных. Это может быть сложной задачей и, в зависимости от контекста, в который попадают данные, может включать комбинацию экранирования JavaScript, HTML‑кодирования и URL‑кодирования в правильной последовательности.

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

DOM clobbering

DOM clobbering — это продвинутая техника, при которой вы внедряете HTML на страницу, чтобы манипулировать DOM и в конечном итоге изменить поведение JavaScript на сайте. Наиболее распространённая форма DOM clobbering использует элемент ссылки, чтобы перезаписать глобальную переменную, которую приложение использует небезопасным образом, например для генерации динамического URL сценария.

Подробнее

DOM clobbering

Last updated