Предотвращение XSS: кодирование вывода и CSP
Изучите отражённые, сохранённые и основанные на DOM атаки XSS, экранируйте вывод, управляемый пользователем, не используйте innerHTML с ненадёжными данными и добавьте заголовок Content Security Policy
«Предотвращение XSS: кодирование вывода и CSP» — бесплатный урок Frontend Academy на CoddyKit. Это урок 1 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Frontend Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Frontend Academy содержит 4 уроков всего.
Что такое XSS?
Межсайтовое выполнение скриптов происходит, когда злоумышленник внедряет исполняемый JavaScript в вашу страницу. Браузер запускает его с правами вашего источника — это позволяет красть cookie, перехватывать сеансы, изменять содержимое страницы и перенаправлять пользователей на вредоносные программы.
Три вида XSS
Сохранённый: вредоносный скрипт сохраняется в базе данных и отправляется каждому посетителю. Отражённый: введённые данные возвращаются в ответе (?q=<script>...). На основе DOM: клиентский JS записывает ненадёжные данные в DOM.
Основная причина: innerHTML с ненадёжными данными
Использование innerHTML (или v-html, dangerouslySetInnerHTML) со строками, которыми управляет пользователь, — основной вектор XSS.
// BAD: user input rendered as HTML
el.innerHTML = userComment; // attacker submits <img onerror=alert(1)>
// Vue equivalent:
<div v-html="userComment"></div> // same bug
// React equivalent:
<div dangerouslySetInnerHTML={{ __html: userComment }} /> // same bugКодирование вывода (безопасный вариант по умолчанию)
Рассматривайте ненадёжные строки как текст, а не как HTML. React, Vue, Angular и Svelte делают это по умолчанию при интерполяции {value}.
// SAFE: text content, not HTML
el.textContent = userComment; // <script> shows as literal text
// React (auto-escaped):
<div>{userComment}</div>
// Vue (auto-escaped):
<div>{{ userComment }}</div>Очистка данных, когда необходимо отображать HTML
Если вам действительно нужно отображать пользовательский HTML (например, в редакторах форматированного текста), выполните очистку с помощью DOMPurify — никогда не создавайте собственный очиститель на основе регулярных выражений.
import DOMPurify from 'dompurify';
const clean = DOMPurify.sanitize(userHtml);
el.innerHTML = clean; // strips <script>, on* handlers, dangerous URLsПроверка URL-адресов
URL-адреса, которыми управляет пользователь, в href или src могут вызвать XSS через схемы javascript:.
// BAD:
<a href={userUrl}>Click</a>
// attacker submits: javascript:alert(1)
// GOOD: whitelist protocols:
function safeUrl(url) {
if (!/^https?:\/\//.test(url) && !url.startsWith('/')) return '#';
return url;
}Политика безопасности содержимого (CSP)
CSP — это заголовок HTTP-ответа, который сообщает браузеру, какие источники скриптов, стилей, изображений и других ресурсов разрешены. Даже если злоумышленник внедрит скрипт, браузер откажется его выполнять.
Content-Security-Policy: default-src 'self'; script-src 'self' https://cdn.trusted.com; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:Строгая CSP с одноразовыми значениями
Для управляемых вами встроенных скриптов используйте отдельное значение nonce для каждого запроса. Во внедрённых злоумышленником скриптах не будет соответствующего nonce.
// Server generates a random nonce per request:
const nonce = crypto.randomBytes(16).toString('base64');
res.setHeader('Content-Security-Policy', `script-src 'nonce-${nonce}' 'strict-dynamic'`);
// Inject into the HTML:
<script nonce="abc123">/* trusted inline code */</script>Файлы cookie HttpOnly + Secure
Устанавливайте cookie сеанса с атрибутом HttpOnly, чтобы JavaScript не мог их прочитать — даже при XSS злоумышленник не сможет получить токен сеанса.
Set-Cookie: session=abc; HttpOnly; Secure; SameSite=StrictЦелостность подключаемых ресурсов (SRI)
При загрузке сторонних скриптов через CDN используйте SRI, чтобы проверить соответствие содержимого хешу. Скомпрометированный CDN не сможет отдать вредоносный скрипт, не нарушив проверку хеша.
<script
src="https://cdn.example.com/lib.js"
integrity="sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC"
crossorigin="anonymous"
></script>Доверенные типы (экспериментальная функция)
Доверенные типы — это функция браузера (на базе Chromium), которая заставляет опасные точки вставки (innerHTML) принимать объект доверенного типа, не позволяя вставлять строки вовсе.
Тестирование на XSS
Попробуйте внедрить <img src=x onerror=alert(1)> в каждое текстовое поле ввода, содержимое которого выводится обратно. Если появится предупреждение, значит, у вас есть уязвимость XSS. Используйте такие инструменты, как OWASP ZAP, для автоматического сканирования.
Быстрая проверка
Почему конструкция React {userInput} безопасна по умолчанию, а dangerouslySetInnerHTML — нет?
Итоги: предотвращение XSS
По умолчанию выводите текст (конструкция React {x} и Vue {{ x }} безопасны). При выводе HTML выполняйте санитизацию с помощью DOMPurify. Разрешайте протоколы URL по белому списку. Заголовок CSP (с одноразовыми значениями или 'strict-dynamic') блокирует внедрённые скрипты. Файлы cookie с атрибутом HttpOnly предотвращают кражу через JS. Используйте хеши SRI для скриптов из CDN. Проверяйте поля ввода с помощью классических полезных нагрузок.
Изучай HTML с ИИ-репетитором — бесплатно
Пиши и запускай код прямо в браузере, получай мгновенную помощь от ИИ-репетитора 24/7 и продолжи учиться на сайте или в приложении.
- Курсы
- 41
- Уроки
- 163
Часто задаваемые вопросы
Урок «Предотвращение XSS: кодирование вывода и CSP» бесплатный?
Да — полный текст урока «Предотвращение XSS: кодирование вывода и CSP» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Frontend Academy, подпишись на CoddyKit PRO. Курс Frontend Academy содержит 4 уроков всего.
Чему я научусь в уроке «Предотвращение XSS: кодирование вывода и CSP»?
Изучите отражённые, сохранённые и основанные на DOM атаки XSS, экранируйте вывод, управляемый пользователем, не используйте innerHTML с ненадёжными данными и добавьте заголовок Content Security Policy Ты практикуешь Frontend Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать Frontend Academy?
Предыдущий опыт не требуется. Frontend Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 1 из 4.
Сколько времени занимает урок «Предотвращение XSS: кодирование вывода и CSP»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке Frontend Academy?
Да. Каждый урок Frontend Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- Предотвращение XSS: кодирование вывода и CSP
- CSRF: файлы cookie SameSite и токены
- Политика безопасности содержимого: nonce и hash
- Потоки OAuth на фронтенде