Загрузка...
Загрузка...
Полное руководство по CSP: все директивы, nonce, hash, report-uri, strict-dynamic. Пошаговое внедрение, отладка, примеры для популярных фреймворков.
Практическое руководство по настройке Content Security Policy для защиты от XSS. Директивы, примеры конфигурации, режим Report-Only и внедрение без поломки сайта.
БезопасностьИспользование Content-Security-Policy-Report-Only для безопасного тестирования CSP. report-uri, Report API, сбор и анализ отчётов перед включением блокировки.
БезопасностьГлубокое руководство по настройке HTTP-заголовков безопасности. Content-Security-Policy, HSTS, X-Frame-Options и другие механизмы защиты от атак на веб-приложения.
БезопасностьНастройка безопасных cookies: Secure, HttpOnly, SameSite. Защита от XSS, CSRF, перехвата. Примеры для разных языков и фреймворков.
Поделитесь с коллегами или изучите другие материалы блога
Content Security Policy (CSP) — стандарт W3C для защиты от XSS и инъекций контента. Политика описывает, из каких источников разрешено загружать скрипты, стили, изображения, шрифты и другие ресурсы. Браузер блокирует всё, что не соответствует правилам.
Проверить и отладить CSP можно с помощью CSP Analyzer и Security Headers на rechecker.ru.
CSP задаётся заголовком Content-Security-Policy или мета-тегом:
<meta http-equiv="Content-Security-Policy" content="default-src 'self'">
Заголовок имеет приоритет над мета-тегом. При наличии обоих применяются оба (ограничения объединяются).
Краткое введение в настройку — в статье Content Security Policy (CSP): настройка и примеры.
| Директива | Контролирует |
|---|---|
| default-src | Fallback для остальных *-src |
| script-src | JavaScript |
| style-src | CSS |
| img-src | Изображения |
| font-src | Шрифты |
| connect-src | XHR, fetch, WebSocket, EventSource |
| media-src | audio, video |
| object-src | object, embed, applet |
| frame-src | iframe, frame |
| worker-src | Web Workers, Service Workers |
| manifest-src | Web App Manifest |
| base-uri | Ограничение тега base |
| form-action | Куда можно отправлять формы |
| Директива | Назначение |
|---|---|
| report-uri | URL для отправки отчётов (устаревает) |
| report-to | Имя группы Report API |
| frame-ancestors | Кто может встраивать страницу в iframe |
| sandbox | Ограничения для iframe |
| Ключевое слово | Описание |
|---|---|
| 'none' | Запретить все источники |
| 'self' | Только тот же origin |
| 'unsafe-inline' | Inline-скрипты и стили (ослабляет защиту) |
| 'unsafe-eval' | eval(), new Function(), setTimeout(string) |
| 'strict-dynamic' | Доверенные скрипты могут загружать другие |
| 'unsafe-hashes' | Разрешить hash для обработчиков событий (опасно) |
https://cdn.example.com — конкретный домен
https://*.example.com — все поддомены
https: — любые HTTPS (осторожно)
data: — data: URI
blob: — blob: URI
'self' — тот же origin
Nonce — случайное значение, меняющееся при каждом запросе. Разрешает конкретные inline-скрипты и стили.
Сервер:
const nonce = crypto.randomBytes(16).toString('base64');
res.setHeader('Content-Security-Policy', `script-src 'self' 'nonce-${nonce}'`);
// Передать nonce в HTML
res.send(`<script nonce="${nonce}">...</script>`);
HTML:
<script nonce="r4nd0mV4lu3">console.log('OK');</script>
Nonce должен быть криптографически случайным и уникальным для каждого ответа.
Hash — SHA-256, SHA-384 или SHA-512 от содержимого скрипта/стиля. Подходит для статического контента.
<script>console.log('hello');</script>
Hash от console.log('hello'); (с пробелами и переносами как в HTML):
'sha256-2qX6...'
Content-Security-Policy: script-src 'self' 'sha256-2qX6...'
При изменении скрипта нужно пересчитать hash.
С 'strict-dynamic' скрипт, загруженный доверенным способом (nonce или hash), может создавать и выполнять новые скрипты. Упрощает работу с динамическими загрузчиками (например, Webpack).
Content-Security-Policy: script-src 'nonce-abc123' 'strict-dynamic'
В современных браузерах 'unsafe-inline' игнорируется при наличии 'strict-dynamic'.
Режим без блокировки — CSP Report-Only: как тестировать политику без блокировки.
Content-Security-Policy-Report-Only: default-src 'self'; report-uri /csp-report
Современный вариант с Report API:
Content-Security-Policy: default-src 'self'; report-to csp-endpoint
Report-To: {"group":"csp-endpoint","max_age":10886400,"endpoints":[{"url":"https://example.com/csp-report"}]}
Формат отчёта (report-uri):
{
"csp-report": {
"document-uri": "https://example.com/page",
"violated-directive": "script-src",
"blocked-uri": "https://evil.com/malicious.js",
"original-policy": "default-src 'self'"
}
}
Ограничивает, кто может встраивать страницу в iframe. Заменяет X-Frame-Options.
Content-Security-Policy: frame-ancestors 'self' https://trusted.com
frame-ancestors 'none' — полный запрет встраивания.
Ограничивает тег <base>, который может менять базовый URL для относительных ссылок.
Content-Security-Policy: base-uri 'self'
Ограничивает URL, на которые можно отправлять формы.
Content-Security-Policy: form-action 'self' https://payment.example.com
Обычно все скрипты бандлятся. Минимальная политика:
Content-Security-Policy: default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; connect-src 'self' https://api.example.com
Много inline-скриптов и сторонних плагинов. Рекомендуется Report-Only, затем постепенное ужесточение. Часто требуется 'unsafe-inline' для script-src до рефакторинга.
// next.config.js
const cspHeader = `
default-src 'self';
script-src 'self' 'unsafe-eval' 'unsafe-inline';
style-src 'self' 'unsafe-inline';
img-src 'self' data: https:;
font-src 'self';
connect-src 'self' https://api.example.com;
`;
В DevTools → Console блокировки CSP выводятся с подробностями. В Network запросы к заблокированным ресурсам помечаются как (blocked:csp).
Онлайн: CSP Analyzer — разбор политики и проверка на типичные ошибки.