Гид по технологиям

Как предотвратить XSS: практическое руководство

7 min read Безопасность Обновлено 12 Apr 2026
Профилактика XSS: практическое руководство
Профилактика XSS: практическое руководство

Программист за ноутбуком, на экране код и окно браузера

Cross‑Site Scripting, широко известный как XSS, — один из самых опасных методов атак, используемых киберпреступниками. Разработчикам и специалистам по безопасности важно понимать, как работает XSS и какие практики блокируют атаки. XSS возникает, когда веб‑приложение показывает пользователю данные, не выполнив их корректную обработку с учётом контекста (HTML, JavaScript, атрибуты DOM).

Что такое XSS — кратко

XSS — это инъекция исполняемого кода (обычно JavaScript) в контент страницы, который затем выполняется в браузере других пользователей. Типы XSS по месту воздействия: отражённый (reflected), хранимый (stored), DOM‑основанный (DOM‑based). Короткое определение терминов:

  • Reflected: ввод из запроса сразу отражается в отклике.
  • Stored: вредоносный ввод сохраняется на сервере (например, в комментариях) и показывается многим пользователям.
  • DOM‑based: уязвимость появляется из‑за динамических операций с DOM на стороне клиента.

Важно: защита зависит от контекста, в котором вы выводите данные. Одна универсальная «волшебная» функции нет — нужно выбирать меры по месту использования.

Как предотвратить XSS через HTML

XSS позволяет злоумышленникам вставлять вредоносные скрипты в веб‑страницы. Пример: гость может оставить сообщение в гостевой книге, и если вы показываете сообщение без экранирования, код исполнится в браузере посетителя.

Предположим, что в поле сообщения злоумышленник вводит:

Если приложение напрямую выводит введённый текст как HTML, браузер выполнит этот скрипт. Чтобы этого не произошло, нужно кодировать специальные символы (<, >, &, \” и \’) перед вставкой в HTML. В контексте HTML (между тегами) используйте HTML‑энкодинг, например htmlspecialchars в PHP или соответствующие функции в других языках/фреймворках.

Советы:

  • Всегда эскейпьте пользовательский ввод при выводе в HTML.
  • Применяйте Content Security Policy (CSP) как дополнительный барьер (например, запрет inline‑скриптов).
  • Для вывода форматированного текста используйте безопасные библиотеки, которые удаляют опасные теги и атрибуты (whitelisting), а не просто удаляют теги полностью.

Как предотвратить XSS через JavaScript

Защита JavaScript‑кода от XSS

Логика HTML также применима к JavaScript. Часто данные из запроса вставляют в DOM с помощью innerHTML, вставки шаблонных строк или document.write — и это даёт атаке возможность выполнить код.

Рассмотрим пример из исходного текста (код сохранён для точности):

Если параметр search содержит пользовательский ввод, и вы используете innerHTML, то атакующий может завершить строку и добавить собственный JavaScript:

filename.php?search=a" alert("The XSS!"); f= "

Результат в коде будет исполнен браузером и атака успешна. Чтобы это предотвратить:

  • Не используйте innerHTML для вывода непроверенных данных. Вместо этого применяйте textContent или setAttribute для безопасного вставления текста.
  • Эскейпьте кавычки и символы меньше/больше, если данные вставляются в JavaScript‑строку или в HTML‑атрибут.
  • Преобразовывайте данные в безопасный формат при интерполяции в шаблонах.

Примеры безопасных приёмов:

  • element.textContent = userInput;
  • element.setAttribute(‘data-value’, safeValue);

Как предотвратить DOM‑основанный XSS

DOM‑XSS появляется, когда JavaScript на клиенте обрабатывает данные (например, из location.hash, search или данных формы) и изменяет DOM напрямую без валидации/эскейпинга.

Пример уязвимого кода (как в исходном материале):

"/>

Атакующий может передать:

filename.php?color=red" onload="alert('The XSS!')

И браузер получит:

Чтобы защититься:

  • Для атрибутов проверяйте формат (например, допустимые значения цвета, URL и т. п.).
  • Эскейпьте кавычки в атрибутах (encodeAttributeValue).
  • Ограничьте значения enum‑списками допустимых опций.
  • В случаях, когда вы ожидаете URL, проверяйте схему (http/https) и не допускайте javascript: в href.

Обратите внимание на пример javascript:href:

Проверяйте и нормализуйте URL перед вставкой в href: допускайте только безопасные схемы (http, https, mailto и т. п.), и используйте относительные пути с осторожностью.

Пример функции защиты XSS на PHP

Защитите сайт от XSS с помощью PHP‑кода

В исходном материале приведена таблица с советами и примером на PHP. Перевод таблицы и пояснения:

Контекст выводаРекомендуемая функция/шаблон
Вставка в HTML‑атрибутhtmlspecialchars($str, ENT_COMPAT) — кодирует двойные кавычки
Вставка в JavaScript/атрибут DOMhtmlspecialchars($str, ENT_NOQUOTES) — не кодирует кавычки, применяйте с осторожностью и только если знаете контекст

| Проверка URL | ‘/^(((https?)|(\/\/))).*/‘ — простая проверка схемы (пример) |

Пример кода из исходника (с сохранением оригинального блока):

Примечания по коду:

  • real_url(data) в примере выглядит как псевдо‑функция — в реальном приложении используйте собственную валидацию/нормализацию URL.
  • ENT_COMPAT кодирует двойную кавычку, ENT_NOQUOTES и ENT_QUOTES используются в зависимости от контекста.

Практическая методология защиты (мини‑метод)

  1. Идентифицируйте контексты вывода (HTML тело, атрибуты, JavaScript, CSS, URL).
  2. Для каждого контекста примените соответствующую функцию кодирования/эскейпинга.
  3. Входные данные валидируйте по белому списку (формат, длина, enum).
  4. По возможности избегайте вставки пользовательского ввода как HTML — используйте textContent/innerText.
  5. Настройте CSP, чтобы ограничить загрузку внешних скриптов и запретить inline‑скрипты.
  6. Регулярно тестируйте приложение с помощью автоматизированных сканеров и ручного тестирования (пентестов).

Чеклист для разработчика и команды безопасности

Разработчик:

  • Использовать textContent вместо innerHTML для вывода текста.
  • Эскейпить данные перед вставкой в HTML/атрибуты/JS/CSS.
  • Проверять схемы URL при приёме ссылок.
  • Ограничивать набор допустимых значений для полей (enum, regex).

Тестировщик/пентестер:

  • Проверить отражённый, хранимый и DOM‑XSS для всех точек ввода.
  • Попробовать payload‑ы с кавычками, закрывающими тег, и вложенными тегами.
  • Проверить настройки CSP и недопустимые источники скриптов.

Администратор/DevOps:

  • Включить и поддерживать CSP, SRI, безопасные заголовки (X‑Content‑Type‑Options, X‑Frame‑Options).
  • Обеспечить обновление библиотек и фреймворков.

Критерии приёмки (Acceptance)

Чтобы фича считалась защищённой от XSS:

  • Никто из тестировщиков не может выполнить JavaScript из пользовательского ввода в любых целевых контекстах.
  • Все поля проходят валидацию и/или безопасный эскейпинг при выводе.
  • CSP настроен и не допускает inline‑скрипты без nonce/hashes (если возможно).
  • Автотесты покрывают основные кейсы эскейпинга.

Плейбук реагирования и SOP — при обнаружении XSS

  1. Изолировать уязвимую функциональность (при возможности выключить/скрыть поле).
  2. Восстановить безопасное значение (удалить вредоносный контент из хранилища).
  3. Провести срочный код‑ревью и патч: корректный эскейпинг/проверка входа.
  4. Развернуть патч и выполнить регрессионные тесты.
  5. Проанализировать логи на предмет эксплойта (какие учётные записи/временные метки).
  6. Уведомить пользователей и, если требуется по политике, регуляторов.

Важно: документировать все шаги и сохранять копии уязвимых данных для последующего анализа.

Тестовые случаи / критерии приёмки

  1. Вводить в поля: , “>”, ‘);alert(1);// — ожидать, что код нигде не исполняется.
  2. Передача в параметре URL специальных последовательностей — проверять, что итоговый DOM безопасен.
  3. Проверка CSP: попытки inline‑выполнения блокируются.
  4. Проверка href: javascript: схемы отвергаются.

Mental models и эвристики

  • Контекст важнее входа: одно и то же значение безопасно в текстовом контексте и опасно внутри атрибута.
  • «Эскейпинг зависит от выхода»: выбирайте метод кодирования по месту вставки.
  • Принцип наименьших привилегий: разрешайте только то, что нужно (white‑list).

Security hardening — дополнительные меры

  • Content Security Policy (CSP): запрет inline‑script и подключений с небезопасных доменов.
  • HTTP‑Only и Secure для cookies.
  • Использование современных фреймворков, которые по умолчанию экранируют шаблоны (например, React, Vue по умолчанию защищают от простого XSS при использовании безопасных практик).
  • Минификация и подпись внешних скриптов (Subresource Integrity — SRI).

Пример потока принятия решения (Mermaid)

flowchart TD
  A[Начало: пользовательский ввод] --> B{Куда вставляется значение?}
  B -->|Текст внутри элемента| C[Использовать textContent]
  B -->|HTML/innerHTML| D[Эскейпить символы <,>,&,',']
  B -->|Атрибут| E[Эскейпить кавычки, проверять enum/формат]
  B -->|JavaScript строка| F[Экранировать кавычки, не использовать eval]
  B -->|href/src| G[Проверить схему 'http/https/ftp' и нормализовать]
  C --> Z[Готово]
  D --> Z
  E --> Z
  F --> Z
  G --> Z

Короткий словарь

  • XSS — Cross‑Site Scripting, инъекция исполняемого кода в контент страницы.
  • CSP — Content Security Policy, заголовок для ограничения ресурсов.
  • Эскейпинг — замена специальных символов на безопасные HTML‑сущности.

Когда предложенные методы могут не сработать (контр‑примеры)

  • Если приложение ошибочно выполняет пользовательский ввод через eval или new Function, эскейпинг может быть проигнорирован.
  • Если сторонняя библиотека манипулирует DOM небезопасно, даже корректный бекенд не спасёт.
  • CSP можно обойти, если разрешены небезопасные источники или включены inline‑скрипты с nonce‑/hash‑неправильной конфигурацией.

Примеры альтернатив и дополнений

  • Использовать строгие шаблонизаторы, которые применяют токенизацию и автоматический эскейпинг.
  • Применять библиотечные санитайзеры (DOMPurify) для случаев, когда нужно разрешить ограничённое форматирование HTML.

Заключение

XSS остаётся одной из самых распространённых и при этом предотвратимых уязвимостей веб‑приложений. Ключи к надёжной защите: понимать контекст вывода, использовать подходящий эскейпинг, валидировать ввод по белому списку и вводить дополнительные барьеры (CSP, SRI, secure headers). Командная ответственность — от разработчиков до DevOps и тестировщиков — снижает риск успешной атаки.

FAQ

Q: Достаточно ли использовать только htmlspecialchars в PHP?

A: Нет. htmlspecialchars защищает при вставке в HTML‑контент, но для других контекстов (JavaScript, CSS, URL, атрибуты) нужны свои методы. Всегда выбирать эскейпинг в зависимости от целевого контекста.

Q: Можно ли полагаться только на Content Security Policy?

A: CSP — мощный дополнительный уровень защиты, но не заменяет корректную обработку входных данных. CSP помогает смягчить последствия, но не устраняет уязвимую логику на сервере или в клиентском коде.

Q: Что безопаснее для вставки текста — textContent или innerHTML?

A: textContent безопаснее, так как вставляет текст без интерпретации HTML. innerHTML интерпретирует HTML и опасен для непроверенных данных.

Поделиться: X/Twitter Facebook LinkedIn Telegram
Автор
Редакция

Похожие материалы

Несколько аккаунтов Skype: Multi Skype Launcher
Программное обеспечение

Несколько аккаунтов Skype: Multi Skype Launcher

Журнал для работы: повысить продуктивность
Productivity

Журнал для работы: повысить продуктивность

Персональные звуки уведомлений на Android
Android.

Персональные звуки уведомлений на Android

Скачивание шоу Hulu для офлайн‑просмотра
Стриминг

Скачивание шоу Hulu для офлайн‑просмотра

Microsoft Start: персонализированная новостная лента
Новости

Microsoft Start: персонализированная новостная лента

Как изменить имя в Epic Games быстро
Гайды

Как изменить имя в Epic Games быстро