XSS при динамическом контенте

При работе с динамическим контентом в веб-приложениях часто возникает уязвимость типа Cross-Site Scripting (XSS). Она проявляется, когда данные, полученные из внешнего источника (пользовательский ввод, API, база данных), вставляются в DOM без должной обработки. Даже при использовании библиотек вроде ScrollMagic для анимации и управления скроллом необходимо учитывать этот риск, поскольку любая вставка контента в HTML может стать точкой атаки.


Виды XSS

  1. Reflected XSS Возникает, когда пользовательские данные немедленно вставляются в страницу и выполняются как код. Пример: данные из строки запроса или формы вставляются в innerHTML без фильтрации.

  2. Stored XSS Данные сохраняются на сервере и впоследствии отображаются в браузере других пользователей. Наиболее опасен в комментариях, форумах, блогах и любых полях, где разрешён HTML.

  3. DOM-based XSS Атака происходит полностью на стороне клиента, когда скрипт манипулирует DOM на основе неконтролируемых данных. ScrollMagic и другие библиотеки могут стать частью цепочки, если динамически создаются элементы и вставляются без экранирования.


Основные источники уязвимостей при динамическом контенте

  • Использование innerHTML или outerHTML для вставки пользовательских данных.
  • Передача непроверенных данных в атрибуты href, src или style.
  • Конкатенация строк с пользовательским вводом в шаблонах для генерации элементов DOM.
  • Взаимодействие с библиотеками анимации и управления скроллом, где элементы создаются динамически и получают HTML-содержимое из внешних источников.

Методы защиты

1. Экранирование HTML

Вставка данных в DOM через textContent вместо innerHTML предотвращает выполнение скриптов:

const message = userInput; // пользовательский ввод
const container = document.getElementById('output');
container.textContent = message; // безопасно

При использовании ScrollMagic для анимации элементов:

const scene = new ScrollMagic.Scene({
    triggerElement: '#trigger'
})
.setClassToggle('#dynamic-element', 'visible')
.addTo(controller);

document.getElementById('dynamic-element').textContent = userInput; // безопасная вставка

2. Использование шаблонизаторов

Современные библиотеки, такие как Handlebars, Mustache, автоматически экранируют пользовательский ввод:

const template = Handlebars.compile("<div>{{content}}</div>");
const html = template({ content: userInput });
document.getElementById('container').innerHTML = html; // безопасно

3. Очистка и фильтрация данных

Для сложных случаев используется санитизация HTML через библиотеки вроде DOMPurify:

const cleanHTML = DOMPurify.sanitize(userInput);
document.getElementById('container').innerHTML = cleanHTML;

Особенно важно при динамическом создании анимированных элементов:

const newElem = document.createElement('div');
newElem.innerHTML = DOMPurify.sanitize(apiData);
scene.setElement(newElem); // безопасное использование с ScrollMagic

4. Избегание динамических скриптов

Нельзя вставлять теги <script> из внешних данных и использовать eval(), new Function() или setTimeout с строковыми аргументами. Любое выполнение кода из пользовательских данных — прямой путь к XSS.


Взаимодействие XSS и ScrollMagic

ScrollMagic управляет сценами, триггерами и классами для элементов DOM. Если элемент создаётся динамически с непроверенным содержимым, возможна комбинация XSS + визуальных эффектов: скрипт может внедряться в элемент, а ScrollMagic — анимировать его видимость, создавая иллюзию легитимного контента.

Пример потенциально уязвимого кода:

const userContent = '<img src=x oner ror=alert(1)>';
const elem = document.createElement('div');
elem.innerHTML = userContent;

new ScrollMagic.Scene({
    triggerElement: '#trigger'
})
.setPin(elem)
.addTo(controller);

В этом примере onerror выполнится при загрузке элемента. Защита — очистка данных до вставки:

elem.textContent = userContent; // безопасно

Практические рекомендации

  • Всегда фильтровать или экранировать все данные перед вставкой в DOM.
  • Использовать textContent или библиотеки-шаблонизаторы, которые экранируют HTML.
  • Для сложного HTML — применять библиотеки санитизации вроде DOMPurify.
  • Проверять, что динамически создаваемые элементы ScrollMagic не получают пользовательский HTML напрямую.
  • Ограничивать разрешённые теги и атрибуты при необходимости вставки HTML.
  • Не доверять внешним API и данным, полученным через клиентский ввод.

Эти меры минимизируют риск XSS при работе с динамическим контентом и библиотеками, управляющими DOM и визуальными эффектами.