DOM clobbering

Что такое DOM clobbering?

DOM clobbering — это техника, при которой вы внедряете HTML на страницу, чтобы манипулировать DOM и в конечном итоге изменить поведение JavaScript на странице. DOM clobbering особенно полезен в случаях, когда XSS невозможен, но вы можете контролировать часть HTML на странице, где атрибуты id или name находятся в белом списке HTML‑фильтра. Наиболее распространённая форма DOM-клобберинга использует элемент ссылки (<a>), чтобы перезаписать глобальную переменную, которая затем используется приложением небезопасным образом, например, для генерации динамического URL сценария.

Термин clobbering происходит от того факта, что вы затираете (clobber) глобальную переменную или свойство объекта, перезаписывая его DOM‑узлом или HTML‑коллекцией. Например, вы можете использовать DOM‑объекты, чтобы перезаписать другие JavaScript‑объекты и эксплуатировать небезопасные имена, такие как submit, вмешиваясь в фактическую функцию формы submit().

Как эксплуатировать уязвимости DOM clobbering

Распространённый шаблон, используемый разработчиками JavaScript:

var someObject = window.someObject || {};

Если вы можете контролировать часть HTML на странице, вы можете заменить ссылку someObject DOM‑узлом, например, элементом ссылки.

Рассмотрим следующий код:

<script>
    window.onload = function(){
        let someObject = window.someObject || {};
        let script = document.createElement('script');
        script.src = someObject.url;
        document.body.appendChild(script);
    };
</script>

Чтобы эксплуатировать этот уязвимый код, вы могли бы внедрить следующий HTML, чтобы заменить ссылку someObject элементом <a>:

Поскольку оба элемента ссылки используют одинаковый id, DOM группирует их вместе в DOM‑коллекцию. Вектор DOM clobbering затем перезаписывает ссылку someObject этой DOM‑коллекцией. Атрибут name используется на последнем элементе ссылки для перезаписи свойства url объекта someObject, указывающего на внешний скрипт.

Другая распространённая техника — использовать элемент form вместе с элементом, таким как input, чтобы перезаписывать свойства DOM. Например, перезапись свойства attributes позволяет обойти клиентские фильтры, которые используют его в своей логике. Хотя фильтр будет перечислять свойство attributes, он фактически не удалит никакие атрибуты, потому что свойство было перезаписано DOM‑узлом. В результате вы сможете внедрять вредоносные атрибуты, которые обычно были бы отфильтрованы. Например, рассмотрим следующую инъекцию:

В этом случае клиентский фильтр будет обходить DOM и встретит элемент form, находящийся в белом списке. Обычно фильтр прошёл бы по свойству attributes элемента form и удалил бы любые атрибуты из чёрного списка. Однако, поскольку свойство attributes было перезаписано элементом input, фильтр вместо этого проходит по элементу input. Так как элемент input имеет неопределённую длину, условия для цикла for фильтра (например, i<element.attributes.length) не выполняются, и фильтр просто переходит к следующему элементу. В результате событие onclick полностью игнорируется фильтром, что впоследствии позволяет вызвать функцию alert() в браузере.

Как предотвратить атаки DOM clobbering

Вы можете предотвратить атаки DOM clobbering, проверяя что объекты или функции являются именно тем, чем вы их считаете. Например, вы можете проверить, что свойство attributes DOM‑узла на самом деле является экземпляром NamedNodeMap. Это гарантирует, что свойство действительно является свойством attributes, а не перезаписанным HTML‑элементом. Вам также следует избегать написания кода, который ссылается на глобальную переменную в сочетании с логическим оператором ||, поскольку это может привести к уязвимостям DOM clobbering.

Резюмируя:

  • Проверяйте, что объекты и функции легитимны. Если вы фильтруете DOM, убедитесь, что проверяете, что объект или функция не является DOM‑узлом.

  • Следует избегать плохих шаблонов кода, таких как использование глобальных переменных в сочетании с логическим оператором ||.

  • Используйте хорошо протестированную библиотеку, такую как DOMPurify, которая учитывает уязвимости DOM clobbering.

Last updated