Content Security Policy (CSP) без поломки сайта
Вы слышали, что Content Security Policy (CSP) необходима для защиты сайта от межсайтового скриптинга (XSS) и атак с внедрением данных. Но когда вы пытаетесь её добавить, сайт ломается: изображения исчезают, скрипты перестают работать, стили пропадают. Кажется, что это компромисс между безопасностью и функциональностью. Но это не обязательно так.
В этом руководстве вы узнаете практический пошаговый подход к внедрению CSP без поломки сайта. Мы рассмотрим основные директивы, использование nonce и хешей, а также безопасное тестирование. В итоге у вас будет работающая CSP, которая повышает безопасность без ущерба для пользовательского опыта.
Что такое CSP и почему она ломает сайты?
Content Security Policy — это стандарт безопасности браузера, который позволяет ограничить, какие ресурсы (скрипты, стили, изображения, шрифты и т.д.) могут загружаться на вашей странице. Он передаётся через HTTP-заголовок, например: Content-Security-Policy: default-src 'self'.
CSP ломает сайты, потому что блокирует любой ресурс, не соответствующий вашей политике. Если у вас есть встроенные скрипты, внешние скрипты с CDN или встроенные стили, они будут заблокированы, если вы явно их не разрешите. По умолчанию блокируется всё, что не разрешено, поэтому строгая политика может быстро сломать сайт.
Ключ в том, чтобы начать с разрешительной политики и постепенно ужесточать её, отслеживая нарушения.
Основные директивы CSP, которые нужно знать
CSP использует директивы для управления различными типами ресурсов. Вот наиболее распространённые:
- default-src: Запасной вариант для других директив. Начните с него.
- script-src: Управляет источниками JavaScript.
- style-src: Управляет источниками CSS.
- img-src: Управляет источниками изображений.
- connect-src: Управляет целями AJAX, WebSocket и fetch.
- font-src: Управляет источниками веб-шрифтов.
- frame-src: Управляет источниками iframe.
- report-uri / report-to: Куда отправлять отчёты о нарушениях.
Вы можете задать несколько директив в одном заголовке, разделяя их точкой с запятой. Например:
Content-Security-Policy: default-src 'self'; script-src 'self' https://trusted.cdn.com; style-src 'self' 'unsafe-inline'; img-src 'self' data: https://images.example.com
Каждая директива принимает разделённый пробелами список источников. Источники могут быть ключевыми словами, такими как 'self', 'unsafe-inline', 'unsafe-eval', или URL, или nonce/хешами.
Пошаговое руководство: внедрение CSP без поломки сайта
Следуйте этим шагам, чтобы безопасно развернуть CSP.
- Начните с политики только для отчётов. Используйте заголовок
Content-Security-Policy-Report-Onlyвместо принудительного. Это позволит увидеть, что было бы заблокировано, без фактической блокировки. - Установите разрешительную политику. Начните с чего-то вроде
default-src 'self' 'unsafe-inline' 'unsafe-eval' https:, чтобы разрешить большинство вещей. Это минимизирует поломки. - Собирайте отчёты о нарушениях. Настройте
report-uriна эндпоинт, который регистрирует нарушения. Просматривайте эти отчёты, чтобы выявить заблокированные ресурсы. - Исправьте нарушения. Обновите код, чтобы избежать встроенных скриптов/стилей, или добавьте nonce/хеши. Переместите внешние ресурсы на разрешённые домены.
- Постепенно ужесточайте политику. Удалите
'unsafe-inline'и'unsafe-eval'после рефакторинга. Сузьте разрешённые домены. - Переключитесь в режим принудительного применения. Как только отчёты не будут показывать неожиданных блокировок, измените заголовок на
Content-Security-Policy(без-Report-Only). - Постоянно мониторьте. Держите эндпоинт для отчётов активным, чтобы ловить новые проблемы.
Этот постепенный подход гарантирует, что вы не сломаете сайт, улучшая безопасность.
Использование nonce и хешей для встроенных скриптов
Встроенные скрипты — частая причина поломки CSP. Вместо разрешения 'unsafe-inline' используйте nonce (одноразовый номер) или хеш.
Подход с nonce: Генерируйте случайный nonce для каждого запроса, добавляйте его в заголовок CSP и включайте в теги script.
Content-Security-Policy: script-src 'nonce-abc123'
<script nonce="abc123">...</script>
Подход с хешем: Вычислите SHA-хеш вашего встроенного скрипта и добавьте его в политику.
Content-Security-Policy: script-src 'sha256-xyz...'
Хеши лучше всего подходят для статических встроенных скриптов, которые редко меняются. Nonce лучше для динамического контента.
Для стилей вы также можете использовать nonce или хеши, но учтите, что style-src с nonce не покрывает встроенные атрибуты стиля (например, style="..."). Для них нужно 'unsafe-inline' или рефакторинг на классы.
Распространённые директивы CSP и их влияние
| Директива | Что контролирует | Типичные источники |
|---|---|---|
| default-src | Запасной вариант для всех типов ресурсов | 'self', https: |
| script-src | Источники JavaScript | 'self', 'nonce-...', 'sha256-...', https://cdn.com |
| style-src | Источники CSS | 'self', 'unsafe-inline', 'nonce-...' |
| img-src | Источники изображений | 'self', data:, https://images.com |
| connect-src | AJAX, WebSocket, fetch | 'self', https://api.com |
| font-src | Веб-шрифты | 'self', https://fonts.gstatic.com |
| frame-src | Iframe | 'self', https://youtube.com |
Используйте эту таблицу как краткий справочник при построении политики.
Тестирование и мониторинг вашей CSP
Перед принудительным применением тщательно протестируйте. Используйте инструменты разработчика браузера: вкладка Console показывает нарушения CSP как ошибки. Вкладка Network показывает заголовок CSP.
Для автоматизированного тестирования рассмотрите такие инструменты, как Google CSP Evaluator (онлайн) или npm-пакет csp_evaluator. Они помогают выявить слабые политики.
Настройте эндпоинт для отчётов, чтобы собирать нарушения в продакшене. Вы можете использовать сервис вроде Report URI или создать свой эндпоинт, который логирует в файл или базу данных. Регулярно анализируйте отчёты, чтобы ловить новые проблемы.
Помните: CSP — не серебряная пуля. Это один из слоёв защиты. Сочетайте её с валидацией входных данных, экранированием выходных данных и другими лучшими практиками безопасности.
FAQ
В чём разница между Content-Security-Policy и Content-Security-Policy-Report-Only?
Принудительный заголовок (Content-Security-Policy) блокирует нарушения. Заголовок только для отчётов (Content-Security-Policy-Report-Only) только сообщает о нарушениях, не блокируя, что позволяет безопасно тестировать политику.
Можно ли использовать CSP с встроенными обработчиками событий, такими как onclick?
Нет, встроенные обработчики событий блокируются CSP, если вы не используете 'unsafe-inline' (что не рекомендуется) или не перейдёте на addEventListener. Для лучшей безопасности избегайте встроенных обработчиков событий.
Как разрешить Google Analytics с CSP?
Добавьте домены Google Analytics в директивы script-src и connect-src. Например: script-src 'self' https://www.googletagmanager.com; connect-src 'self' https://www.google-analytics.com. Проверьте документацию Google для последних требований.
Внедрение CSP не должно быть болезненным процессом. С постепенным подходом вы можете защитить пользователей от XSS и других атак, не нарушая работу сайта. Начните с режима только для отчётов, исправьте нарушения и со временем ужесточите политику.
Если вам нужно быстро отформатировать или проверить JSON-файлы конфигурации для ваших отчётов CSP, попробуйте наш JSON Formatter для форматирования и отладки данных JSON.