Frontend Academy · Урок

Предотвращение XSS: кодирование вывода и CSP

Изучите отражённые, сохранённые и основанные на DOM атаки XSS, экранируйте вывод, управляемый пользователем, не используйте innerHTML с ненадёжными данными и добавьте заголовок Content Security Policy

Урок 1 из 414 шагов

«Предотвращение 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 — локальная установка не требуется.

Все уроки этого курса

  1. Предотвращение XSS: кодирование вывода и CSP
  2. CSRF: файлы cookie SameSite и токены
  3. Политика безопасности содержимого: nonce и hash
  4. Потоки OAuth на фронтенде
← Назад к Frontend Academy