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

Как предотвратить XSS (Cross‑Site Scripting): практическое руководство

6 min read Веб‑безопасность Обновлено 17 Dec 2025
Как предотвратить XSS: практическое руководство
Как предотвратить XSS: практическое руководство

Человек пишет код на открытом ноутбуке

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

Этот материал объясняет практические приёмы защиты XSS на трёх уровнях вывода данных: HTML, JavaScript (включая innerHTML) и свойства DOM. Также приведены дополнительные методики, чеклисты и тесты для команд.

Что такое XSS — одно‑два предложения

XSS — это когда данные из внешнего источника (URL, форма, API) попадают в HTML/JS/DOM без корректного кодирования или валидации и выполняются в браузере.

Основные принципы защиты

  • Отделяйте вход (валидация/нормализация) от вывода (кодирование/экранирование).
  • Никогда не доверяйте данным от клиента.
  • Используйте проверенные библиотеки для очистки HTML/DOM.
  • Внедряйте Content Security Policy (CSP) и безопасные заголовки.

Как предотвратить XSS с помощью HTML

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

Атака: злоумышленник вставляет:

Если сайт просто вставляет пользовательский текст в страницу без экранирования, скрипт выполнится.

Решение: при выводе в HTML экранируйте специальные символы: <, >, &, “ и ‘. Для большинства языков и шаблонных движков есть готовые функции (например, htmlspecialchars в PHP, escapeHtml в многих фреймворках).

Пример безопасного вывода в шаблоне (псевдокод):



{{ user_input }}
{{ user_input | escape_html }}

Важно: отличайте экранирование для HTML от экранирования для атрибутов, JavaScript и URL.

Как предотвратить XSS с помощью JavaScript (innerHTML и подобное)

Сделать JavaScript устойчивым к XSS

В JavaScript опасно использовать innerHTML, document.write() и другие методы, которые парсят строку как HTML. Рассмотрим пример:

Если параметр search в URL содержит:
filename.php?search=a” alert(“The XSS!”); f=”

То итоговый код будет исполняться и приведёт к выполнению alert(). Аналогичная техника — закрывающий тег скрипта в параметре:

filename.php?search=";Fatih

Чтобы избежать этого:

  • Избегайте innerHTML для вывода непроверенных строк. Используйте textContent или createTextNode, которые вставляют текст без парсинга HTML.
  • Если нужно вставлять HTML, пропускайте его через проверенную библиотеку очистки (например, DOMPurify) и строго ограничивайте допустимые теги/атрибуты.
  • Экранируйте кавычки при вставке в атрибуты через JavaScript.

Пример безопасной замены innerHTML:

const el = document.getElementById('print');
// безопасно: вставляет текст, а не HTML
el.textContent = userInput;

// если нужен HTML — очищаем библиотекой
el.innerHTML = DOMPurify.sanitize(userInput);

Как предотвратить XSS через DOM‑атрибуты и URL

Иногда пользовательские данные используются как значения атрибутов (bgcolor, href, src). Пример:

Атака: filename.php?color=red” onload=”alert(‘The XSS!’)

Результат вставки позволяет выполнить onload в body. Требуется кодирование символа “. Общие рекомендации:

  • Для значений атрибутов применяйте экранирование соответствующее контексту (HTML‑атрибут).
  • Для URL в href/src используйте проверку схемы (https/http) или фильтр: разрешайте только допустимые схемы.
  • Не допускайте javascript: в href. Проверяйте, что значение — допустимый абсолютный или относительный URL.

Пример проверки в псевдокоде:

function isSafeUrl(url) {
  // Разрешаем только http, https и протоколозависимые относительные пути
  return /^((https?:)|\/\/|\/)\/.test(url) || /^\//.test(url);
}

if (isSafeUrl(userHref)) {
  link.href = userHref;
} else {
  link.href = '/';
}

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

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

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

Примечание: для продакшена используйте filter_var($url, FILTER_VALIDATE_URL) и библиотеки для более строгой валидации.

Таблица приёмов и соответствующих функций (пример для PHP)

Контекст выводаЧто кодироватьРекомендация (PHP)Комментарий

| HTML — содержимое элемента | <, >, & | htmlspecialchars($str, ENT_QUOTES | ENT_HTML5) | Для текста внутри тега | | HTML — атрибуты | “, ‘ | htmlspecialchars($str, ENT_COMPAT) | Для значений атрибутов | | URL / href | схема/префикс | проверка регуляркой или filter_var | Заблокировать javascript: |

Эти примеры служат общей подсказкой; конкретные реализации зависят от языка и фреймворка.

Когда базовые меры не сработают (контрпримеры)

  • Приложение динамически строит HTML в нескольких контекстах (атрибут, JS‑строка, CSS) и неправильно применяет одно экранирование для всех.
  • Старые браузеры или нестандартные парсеры HTML могут интерпретировать данные иначе.
  • Если вы используете внутренние функции, которые возвращают уже «отформатированный» HTML от стороннего модуля — данные всё ещё могут содержать опасный контент.

В таких случаях нужен многоступенчатый подход: контекстно‑зависимое экранирование + библиотека очистки + CSP.

Альтернативные подходы и инструменты

  • Использовать шаблонизаторы, которые делают автоэкранирование по умолчанию (Twig, Handlebars, Razor и др.).
  • Использовать DOMPurify или аналог для очистки пользовательского HTML.
  • В фронтенде — избегать innerHTML, применять textContent и безопасные шаблоны.
  • Ввести strict Content Security Policy (CSP) с запретом inline‑скриптов и подключением только доверённых источников.

Модель мышления (heuristic)

  • Где данные могут попасть в браузер? URL, формы, API, заголовки, файлы.
  • В каких контекстах данные выводятся? HTML, атрибут, JS‑строка, CSS, URL. Для каждого контекста — своё кодирование.
  • Всегда минимизируйте «разрешённый» набор: если нужен только текст — не разрешайте теги.

Мини‑методология фикса XSS (для инцидента)

  1. Описание инъекции: откуда пришли данные, где отображаются.
  2. Воспроизведение: создать PoC в локальной среде.
  3. Временная защита: блокировать вход/выход (экранирование) и применить CSP.
  4. Исправление: скорректировать код, применить контекстное кодирование и модульные тесты.
  5. Развёртывание и мониторинг.

Чеклист ролей

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

    • Применил контекстное экранирование для каждого места вывода.
    • Заменил innerHTML на textContent там, где вывод — текст.
    • Добавил unit/integration тесты для примеров инъекций.
  • QA / Тестировщик:

    • Прогнал негативные кейсы с типичными полезными нагрузками XSS.
    • Проверил заголовки CSP и поведение при блокировке inline‑скриптов.
  • DevOps / SRE:

    • Внёс CSP и другие HTTP‑безопасные заголовки на уровень сервера/ingress.
    • Настроил мониторинг ошибок JavaScript и отчёты о нарушениях CSP.
  • Информационная безопасность:

    • Провёл ручной и автоматизированный pentest, включая сканирование XSS.
    • Дал рекомендации по библиотекам очистки и политике релизов.

Критерии приёмки

  • Никакой пользовательский ввод не интерпретируется как HTML/JS без явной и безопасной очистки.
  • Unit‑тесты покрывают основные PoC XSS (3–5 вариаций) и проходят в CI.
  • CSP установлен хотя бы в режиме report‑only и не допускает inline‑скриптов.
  • Логи/метрики фиксируют попытки инъекций и уведомляют команду.

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

  • Передавать в поля: , “>, javascript:alert(1). Ожидаемый результат: приложение не выполняет код.
  • Проверить href с javascript: и data: — ожидаемая поведение: отвергнуть или заменить на безопасный URL.

Риски и смягчения

  • Риск: потеря данных сессии и учётных записей через кражу cookies.
    Смягчение: HttpOnly и Secure для cookies, SameSite.
  • Риск: обход CSP через JSONP/внешние библиотеки.
    Смягчение: запретить ненужные источники и тщательно ревью внешних скриптов.

Примечания по приватности

Если вы сохраняете пользовательский ввод (комментарии, профили), подумайте о хранении только минимально необходимой информации. При обработке персональных данных соблюдайте требования локального законодательства о защите данных (например, GDPR/другие регуляции в вашей юрисдикции).

Короткая сводка для команды (SOP)

  1. Всегда валидируйте вход.
  2. Экранируйте контекстно (HTML, атрибут, JS, URL).
  3. Используйте проверенные библиотеки для очистки HTML.
  4. Внедрите CSP и безопасные заголовки.
  5. Покрывайте правки тестами и мониторьте попытки инъекций.

Глоссарий (в одну строку)

  • XSS: внедрение и исполнение вредоносного скрипта в браузере пользователя;
  • CSP: Content Security Policy — набор правил, ограничивающих источник исполняемого кода;
  • innerHTML/textContent: методы DOM для вставки HTML или текста.

Итог

XSS остаётся распространённой и серьёзной угрозой, но её можно системно устранить, применяя контекстное экранирование, безопасные шаблонизаторы, проверенные библиотеки очистки и политики безопасности (CSP, заголовки). Команда должна иметь процессы для обнаружения, быстрого патча и тестирования фиксов.

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

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

Кастомные меню в Godot — старт, пауза, Game Over
Разработка игр

Кастомные меню в Godot — старт, пауза, Game Over

Исправление BSoD btha2dp.sys — Bluetooth в Windows
Windows

Исправление BSoD btha2dp.sys — Bluetooth в Windows

Наложение производительности Windows 11 — как включить
Windows 11

Наложение производительности Windows 11 — как включить

Гостевой аккаунт в Windows 11 — как создать
Windows 11

Гостевой аккаунт в Windows 11 — как создать

Удаление Facebook Messenger на ПК — инструкция
Инструкции

Удаление Facebook Messenger на ПК — инструкция

10 бесплатных кистей Photoshop и как установить
Дизайн

10 бесплатных кистей Photoshop и как установить