XSS через innerHTML и способы защиты
Разберитесь в межсайтовом скриптинге и безопасных альтернативах innerHTML
«XSS через innerHTML и способы защиты» — бесплатный урок HTML Academy на CoddyKit. Это урок 2 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения HTML Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс HTML Academy содержит 4 уроков всего.
Основная уязвимость
Присваивание el.innerHTML = userInput разбирает строку как HTML. Если userInput содержит теги <script> или атрибуты обработчиков событий (onclick, onerror), браузер интерпретирует их и выполняет управляемый злоумышленником код на странице.
Почему это распространено
Любой код, который вставляет пользовательские данные в HTML — шаблоны на сервере или отображение на стороне клиента, — создаёт риск XSS, если данные не экранированы. Одностраничные приложения, создающие innerHTML из ответов интерфейсов, особенно уязвимы, когда эти ответы содержат пользовательское содержимое.
Конкретный пример
Имя пользователя "Bob<img src=x onerror=alert(1)>", установленное через div.innerHTML = `Welcome, ${user}`, выполняет alert(1), когда изображение не удаётся загрузить. Те же данные в виде обычного текста (через textContent) безвредны: браузер видит только символы, а не теги.
// VULNERABLE
div.innerHTML = `Hi, ${user.name}`;
// SAFE
div.textContent = `Hi, ${user.name}`;Используйте textContent для обычного текста
textContent задаёт только текст — специальные символы HTML отображаются как обычные символы и никогда не становятся тегами. В 90% случаев это правильный инструмент. Переходите на innerHTML только тогда, когда действительно нужно отобразить разметку, а не текст.
Используйте методы DOM для создания структуры
Чтобы создавать элементы с пользовательскими данными, формируйте их с помощью createElement и textContent: const li = document.createElement("li"); li.textContent = name; ul.appendChild(li);. Результат структурно идентичен innerHTML, но по своей конструкции защищён от XSS.
Когда необходимо использовать innerHTML
Для доверенного HTML, сгенерированного сервером (вывод собственного шаблона или очищенный форматированный текст из доверенного редактора), innerHTML подходит. Никогда не применяйте его непосредственно к данным из ненадёжных источников без очистки.
Очищайте форматированный текст с помощью DOMPurify
Если пользователи отправляют форматированный текст (например, из редактора комментариев или при отображении markdown), очистите его перед присваиванием innerHTML: el.innerHTML = DOMPurify.sanitize(richHtml). DOMPurify удаляет опасные теги и атрибуты, сохраняя безопасное форматирование, например <b>, <em> и <a>.
insertAdjacentHTML несёт тот же риск
el.insertAdjacentHTML("beforeend", html) разбирает строки HTML, создавая такую же поверхность для XSS, как innerHTML. Правила те же: никогда не передавайте пользовательские данные напрямую; очищайте их или используйте методы DOM. То же относится к document.write, хотя сейчас этот метод уже никто не должен использовать.
Настройки фреймворков по умолчанию
React, Vue, Svelte и Angular по умолчанию экранируют интерполированный текст — {name} безопасен. Они предоставляют обходные механизмы (dangerouslySetInnerHTML в React и v-html в Vue), которые несут такой же риск XSS; используйте их экономно и только с очисткой данных.
Внедрение через атрибуты
Даже значения атрибутов могут стать вектором атаки: <a href={url}> с url="javascript:alert(1)" выполняется при щелчке. Проверяйте адреса по схеме (разрешайте только http:, https:, mailto: и tel:) перед помещением пользовательского ввода в href, src или другие атрибуты, содержащие адреса.
Политика Trusted Types
Современные браузеры поддерживают Trusted Types: настройте CSP с помощью require-trusted-types-for 'script', и innerHTML откажется принимать необработанные строки — пройдут только значения, обёрнутые политикой. Это делает XSS невозможным благодаря программному интерфейсу, а не одной лишь внимательности разработчиков.
Многоуровневая защита
Одного уровня недостаточно. Сочетайте проверку вводимых данных на сервере, экранирование вывода при отображении, CSP для блокировки внедрённых скриптов, доверенные типы для запрета необработанных строк и проверку безопасности любого использования innerHTML. Многоуровневая защита выдерживает ошибку на любом отдельном уровне.
Проверка знаний
Почему el.textContent = userInput защищает от XSS, а el.innerHTML = userInput представляет опасность?
Итоги
Использование innerHTML для пользовательского ввода — классический вектор XSS. Используйте textContent для текста, createElement и textContent для структуры, а при необходимости расширенного HTML — библиотеку для очистки HTML. Проверяйте схемы адресов в значениях атрибутов. Добавляйте CSP и доверенные типы, чтобы нейтрализовать ошибки, пропущенные при проверке кода. Современные фреймворки экранируют данные по умолчанию — используйте их небезопасные обходные механизмы как можно реже и обязательно проверяйте их.
Часто задаваемые вопросы
Урок «XSS через innerHTML и способы защиты» бесплатный?
Да — полный текст урока «XSS через innerHTML и способы защиты» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс HTML Academy, подпишись на CoddyKit PRO. Курс HTML Academy содержит 4 уроков всего.
Чему я научусь в уроке «XSS через innerHTML и способы защиты»?
Разберитесь в межсайтовом скриптинге и безопасных альтернативах innerHTML Ты практикуешь HTML Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать HTML Academy?
Предыдущий опыт не требуется. HTML Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 2 из 4.
Сколько времени занимает урок «XSS через innerHTML и способы защиты»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке HTML Academy?
Да. Каждый урок HTML Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- Политика безопасности содержимого: meta http-equiv
- XSS через innerHTML и способы защиты
- Песочница iframe и политика разрешений
- HTTPS и целостность подресурсов