Skip to content
← Все статьи

Защита от XSS атак: типы, эскейпинг, CSP, Trusted Types

Защита от XSS атак: типы, эскейпинг, CSP, Trusted Types

XSS (Cross-Site Scripting) — исполнение злоумышленником произвольного JavaScript в контексте вашего домена. Последствия: кража session cookies, keylogging, фишинг, полный захват аккаунта. XSS входит в OWASP Top 10: Injection и остаётся в топе находок любого pentest. В статье — три типа XSS, правильный эскейпинг по контексту, CSP и Trusted Types как defense-in-depth.

Три типа XSS

Контекстный эскейпинг

Главное правило: эскейпинг зависит от контекста вывода.

<!-- HTML body -->
<div>{{ escaped_html }}</div>       ← &, <, >, ", '

<!-- HTML attribute -->
<img alt="{{ escaped_attr }}">        ← то же + кавычки

<!-- JS string literal -->
var x = "{{ escaped_js }}";           ← экранировать \, ', ", newline, unicode

<!-- URL attribute -->
<a href="{{ url_encoded }}">          ← rawurlencode + whitelist scheme

<!-- CSS value -->
color: {{ css_escaped }};              ← только [a-zA-Z0-9#%]

PHP

function e(string $s): string {
  return htmlspecialchars($s, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
}

echo '<div>', e($userInput), '</div>';

JavaScript (DOM)

// Опасно
element.innerHTML = userInput;

// Безопасно
element.textContent = userInput;

// Если нужен HTML — используйте DOMPurify
import DOMPurify from 'dompurify';
element.innerHTML = DOMPurify.sanitize(userInput);

React / Vue

React по умолчанию эскейпит содержимое {variable}. Опасна только конструкция dangerouslySetInnerHTML и нединамические href:

// ❌
<a href={userInput}> ... // javascript: схема

// ✅
const safeHref = userInput.startsWith('http') ? userInput : '#';
<a href={safeHref}>

CSP как последняя линия

Даже идеальный эскейпинг не спасёт от нулевого-дня в фреймворке. CSP превращает успешный XSS в заблокированный скрипт. Минимум:

Content-Security-Policy: default-src 'self'; script-src 'self' 'nonce-RANDOM' 'strict-dynamic'; object-src 'none'; base-uri 'self'

Детали — в CSP setup.

Trusted Types (Chrome 83+)

Trusted Types — механизм, который заставляет все DOM sink'и (innerHTML, script.src) принимать только «доверенные» строки, прошедшие через policy-функцию. Значительно уменьшает DOM-based XSS:

Content-Security-Policy: require-trusted-types-for 'script'; trusted-types default
trustedTypes.createPolicy('default', {
  createHTML: (s) => DOMPurify.sanitize(s),
});
element.innerHTML = 'raw html'; // TypeError без policy

HTTP-only cookies

Флаг HttpOnly не даёт JS читать cookie — даже при успешном XSS session не утечёт. Обязательно вместе с Secure и SameSite. Детали — Cookie Security.

Server-side проверки

Проверка

Тест-payload: <img src=x onerror="alert(1)">. Если алерт сработал в браузере — у вас XSS. Статический анализ — Semgrep, Snyk Code, SonarQube. Регулярный аудит security headers через Security Scanner.

FAQ

Достаточно ли strip_tags в PHP? Нет — обходится через <svg>, onerror, HTML-entities. Только htmlspecialchars для body и DOMPurify/HTMLPurifier для rich-content.

Защищает ли SSL/TLS проверку от XSS? Нет — XSS живёт внутри исполненного JS на легитимном домене.

jQuery .html() опасен? Да — это обёртка вокруг innerHTML. Используйте .text().

Что с Markdown-инпутом? Парсите в sanitized HTML через marked + DOMPurify, не пропускайте raw HTML.

Вывод

Слоёная защита: контекстный эскейпинг + CSP + Trusted Types + HttpOnly cookies + WAF. Мониторьте CSP-отчёты через мониторинг и проверяйте конфигурацию в Security Scanner. Связанное чтение: CSP Setup, Cookie Security.

Проверьте ваш сайт прямо сейчас

Проверить →
Другие статьи: SEC
SEC
WAF (Web Application Firewall): базовый гайд
15.04.2026 · 5 просм.
SEC
CORS: полное руководство по Access-Control-Allow
15.04.2026 · 2 просм.
SEC
Subresource Integrity (SRI): защита CDN-скриптов
15.04.2026 · 5 просм.
SEC
Защита от SQL injection: prepared statements и ORM
15.04.2026 · 4 просм.