OWASP • XSS Protection

Защита от XSS атак

📋

Чек-лист разработчика

18 пунктов по материалам этой страницы — для code review и аудита. Можно скачать списком в .txt.

Показать все пункты на странице

XSS — это уязвимость, при которой злоумышленник внедряет JavaScript, который выполняется в браузере пользователя.

Чтобы защититься, нужно комбинировать несколько уровней защиты: encoding, validation, sanitization и безопасные DOM API.

Главный принцип

Любые данные пользователя считаются потенциально вредоносными до момента их безопасной обработки.

Цель атаки

Найти место, где данные становятся кодом, а не текстом.

📥 Input Validation (валидация)

Валидация — это проверка данных до их обработки. Она решает: принимать или отклонять данные.

В отличие от encoding, она не "чинит" данные, а блокирует неправильные.

🔍

Что это?

Валидация — проверка входных данных на соответствие ожидаемому формату (email, число, дата, URL и т.д.).

Для чего используется?

Отсеивает явно вредоносные или некорректные данные ДО того, как они попадут в систему. Например, если поле ожидает число — отклоняем всё, что содержит теги <script>. Это первый барьер защиты.

📌 Пример: проверка email через regex, reject HTML-тегов в имени пользователя

🔄 Output Encoding (экранирование)

Преобразует данные в безопасный формат, чтобы браузер не воспринимал их как код.

HTML

< → &lt;

URL

%HH encoding

JS

\uXXXX

CSS

\XX encoding

🛡️

Что это?

Экранирование (кодирование) — замена опасных символов на их безопасные HTML-сущности или escape-последовательности.

Для чего используется?

Превращает <script>alert(1)</script> в безобидный текст &lt;script&gt;alert(1)&lt;/script&gt;. Браузер показывает это как текст, а НЕ выполняет как код. Обязательно применять ПЕРЕД выводом данных в HTML, атрибуты, JavaScript, CSS, URL.

📌 Контексты: HTML body, атрибуты, JavaScript строки, CSS, URL — для каждого своё кодирование!

✅ Safe Sinks

Sink — это место, куда попадают данные. Safe sinks не выполняют код.

  • • textContent
  • • setAttribute
  • • className
  • • value
  • • createTextNode

⚠️ Dangerous Sinks

Эти точки интерпретируют данные как код.

  • • innerHTML
  • • document.write
  • • eval
  • • setTimeout(string)
  • • onclick handlers

🧼 HTML Sanitization

Sanitization удаляет опасный HTML (script, event handlers), но сохраняет форматирование.

let clean = DOMPurify.sanitize(dirty);
                    
🧹

Что это?

Санитизация — очистка HTML от потенциально опасных тегов и атрибутов (например, <script>, onclick=, javascript:), но с сохранением безопасного форматирования (<b>, <i>, <a href>).

Для чего используется?

Когда пользователю РАЗРЕШЕНО вводить HTML (редакторы, комментарии с форматированием), но нужно убрать вредоносный код. Лучшая библиотека — DOMPurify. В отличие от экранирования, санитизация позволяет использовать теги, но в безопасном виде.

📌 Пример: DOMPurify.sanitize("<b>привет</b><script>alert(1)</script>") → "<b>привет</b>"

🛡️ Дополнительные защиты

Content Security Policy
ограничивает выполнение скриптов
Safe DOM API
отказ от innerHTML
Cookies flags
HttpOnly / Secure / SameSite
Trusted Types
защита DOM XSS
🔒

Content Security Policy (CSP)

Что: HTTP-заголовок, белый список источников загрузки ресурсов.

Зачем: Блокирует inline-скрипты и выполнение кода с недоверенных доменов. Даже если XSS есть — скрипт не выполнится.

Пример: Content-Security-Policy: script-src 'self'

Trusted Types

Что: Современный браузерный API, требующий явного создания "безопасных" строк перед передачей в dangerous sinks (innerHTML).

Зачем: Полностью исключает DOM XSS — браузер не выполнит строку, если она не прошла через TrustedTypePolicy.

Пример: const policy = trustedTypes.createPolicy(...)

🛠️

Safe DOM API

Что: Использование textContent, setAttribute, createElement вместо innerHTML, insertAdjacentHTML.

Зачем: Автоматическая обработка данных как текст, не как HTML. Безопасно по умолчанию, не требует экранирования.

✅ element.textContent = userInput (безопасно!)

🍪

Флаги Cookies

Что: HttpOnly, Secure, SameSite флаги для кук.

Зачем: HttpOnly — защита от кражи сессии через XSS (JavaScript не видит куку). Secure — только по HTTPS. SameSite — защита от CSRF.

Set-Cookie: sessionId=...; HttpOnly; Secure; SameSite=Strict

Защита в глубину (Defense in Depth)

Ни один метод не даёт 100% гарантии. Комбинируйте:
1️⃣ Валидация — отклоняем плохие данные
2️⃣ Экранирование — нейтрализуем опасные символы
3️⃣ Санитизация — чистим разрешённый HTML
4️⃣ Safe API — не используем innerHTML где не нужно
5️⃣ CSP — страховка, если что-то прошло
6️⃣ Trusted Types — современная защита
7️⃣ HttpOnly — защита сессий