Content security policy это: настройка и проверка заголовков


HTTP-заголовки безопасности служат основой защиты от различных угроз, таких как межсайтовый скриптинг (XSS), кликджекинг и атаки с внедрением данных. Однако в 2024 году только около 12% из топ-1 миллиона сайтов применяют Content Security Policy. В своей практике я неоднократно наблюдал, как правильная настройка этих заголовков предотвращает множество уязвимостей всего за несколько минут. В этом руководстве вы найдете подробные рекомендации и примеры конфигураций для Nginx и Apache.

Почему заголовки безопасности важны

Заголовки безопасности направляют браузеры в том, как обрабатывать ваш контент — определяют допустимые скрипты, возможность встраивания страницы в фрейм и передачи данных через рефереры. Их внедрение не требует затрат и обеспечивает защиту от множества атак, перечисленных в OWASP Top 10.

📖 Определение — HTTP-заголовки безопасности (HTTP Security Headers) — это заголовки ответа, отправляемые сервером, которые активируют механизмы безопасности на стороне браузера, ограничивая поведение, которое могут эксплуатировать злоумышленники.

Если вы выстраиваете защиту веб-приложения на уровне браузера, полезно отдельно посмотреть Безопасность API в 2026 году: поверхность атаки, которую пентест часто упускает, чтобы не ограничиваться только HTTP-заголовками и видеть полный контур риска.

Content Security Policy (CSP): что это и как настроить

CSP — самый мощный заголовок безопасности. Он определяет список разрешённых источников контента, эффективно нейтрализуя XSS, внедрение данных и несанкционированные встроенные скрипты.

Content-Security-Policy: default-src 'self'; script-src 'self' https://cdn.example.com; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' https://fonts.gstatic.com; connect-src 'self' https://api.example.com; frame-ancestors 'none'; base-uri 'self'; form-action 'self'; upgrade-insecure-requests;
ДирективаУправляетРекомендуемое значение
default-srcЗапасной вариант для всех типов ресурсов‘self’
script-srcИсточники JavaScript‘self’ + конкретные CDN
style-srcИсточники CSS‘self’ (избегайте ‘unsafe-inline’)
img-srcИсточники изображений‘self’ data: https:
frame-ancestorsКто может встраивать вашу страницу‘none’
base-uriОграничивает элемент <base>‘self’

🎯 Начните с режима Content-Security-Policy-Report-Only, чтобы фиксировать нарушения без блокировки. Используйте директиву report-uri или report-to для сбора отчётов, затем итеративно ужесточайте политику.

🚫 Никогда не используйте 'unsafe-eval' в продакшен-CSP. Это повторно включает eval(), полностью подрывая защиту от XSS. Переработайте код, который вызывает eval(), new Function() или встроенные обработчики событий.

После настройки заголовков безопасности полезно отдельно посмотреть Firebase Cloud Functions: создание безопасных функций с правами администратора, чтобы сопоставить защиту фронтенда с практиками hardening на серверной стороне.

Strict-Transport-Security (HSTS): настройка заголовка

Принуждает браузеры подключаться только через HTTPS, предотвращая атаки на понижение протокола и SSL-стриппинг (SSL stripping).

Strict-Transport-Security: max-age=63072000; includeSubDomains; preload

X-Frame-Options

Предотвращает встраивание вашей страницы в элементы <iframe>, <frame> или <object> на других сайтах — блокируя атаки кликджекинга (clickjacking).

X-Frame-Options: DENY
ЗначениеПоведение
DENYНикогда не разрешать фреймирование (наиболее безопасно)
SAMEORIGINРазрешать фреймирование только с того же источника

💡 Директива frame-ancestors в CSP предлагает современный и более детальный подход по сравнению с X-Frame-Options, обеспечивая гибкость в управлении фреймами. Рекомендуется использовать оба заголовка для максимальной совместимости с устаревшими браузерами.

X-Content-Type-Options

Предотвращает MIME-сниффинг (MIME sniffing) — ситуацию, когда браузер интерпретирует ответ в обход объявленного Content-Type. Блокирует атаки, которые маскируют исполняемый контент под безвредные типы файлов.

X-Content-Type-Options: nosniff

Это один из самых простых заголовков в настройке: одна строка конфигурации закрывает целый класс атак через подмену типа контента

Referrer-Policy

Управляет тем, какой объём информации о реферере (referrer) отправляется при переходе с вашего сайта на внешние ресурсы.

Referrer-Policy: strict-origin-when-cross-origin

Значение strict-origin-when-cross-origin — разумный баланс: при переходах внутри одного источника передаётся полный URL, при кросс-доменных переходах — только домен, а при переходе с HTTPS на HTTP реферер не передаётся вовсе.

Permissions-Policy

Управляет тем, какие функции браузера — камера, микрофон, геолокация и другие — могут использовать ваш сайт и встроенные iframe. Ранее этот заголовок назывался Feature-Policy.

Permissions-Policy: camera=(), microphone=(), geolocation=(), payment=(self), usb=()

Совет: установите для неиспользуемых функций значение () (пустой список разрешений), чтобы явно отключить их. Это предотвращает скрытый доступ встроенных сторонних скриптов к чувствительным API — таким как камера или микрофон.

Дополнительные полезные заголовки

ЗаголовокЗначениеНазначение
Cross-Origin-Opener-Policysame-originИзолирует контекст просмотра, включает SharedArrayBuffer
Cross-Origin-Embedder-Policyrequire-corpГарантирует, что все встроенные ресурсы явно разрешают загрузку
Cross-Origin-Resource-Policysame-originПредотвращает загрузку ваших ресурсов другими источниками
X-DNS-Prefetch-ControloffПредотвращает спекулятивные DNS-запросы (конфиденциальность)

Эти заголовки особенно важны для приложений, использующих SharedArrayBuffer или требующих строгой изоляции кросс-доменных ресурсов.

Настройка HTTP Security Headers в Nginx и Apache

Nginx

# /etc/nginx/snippets/security-headers.conf
add_header Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self'; img-src 'self' data: https:; frame-ancestors 'none'; base-uri 'self'; form-action 'self';" always;
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
add_header X-Frame-Options "DENY" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always;
add_header Cross-Origin-Opener-Policy "same-origin" always;
add_header Cross-Origin-Embedder-Policy "require-corp" always;
# Include in server block:
# include snippets/security-headers.conf;

Apache

# .htaccess or httpd.conf
Header always set Content-Security-Policy "default-src 'self'; script-src 'self'; frame-ancestors 'none';"
Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"
Header always set X-Frame-Options "DENY"
Header always set X-Content-Type-Options "nosniff"
Header always set Referrer-Policy "strict-origin-when-cross-origin"
Header always set Permissions-Policy "camera=(), microphone=(), geolocation=()"

Лучшие практики

  • Сначала разверните CSP в режиме report-only, проанализируйте нарушения, затем включите принудительное применение
  • Используйте CSP на основе nonce ('nonce-{random}') вместо 'unsafe-inline' для встроенных скриптов
  • Добавляйте ключевое слово always в Nginx, чтобы заголовки отправлялись при всех кодах ответа (включая 4xx/5xx)
  • Тестируйте заголовки в staging-среде перед продакшеном — слишком строгий CSP может сломать легитимную функциональность
  • Регулярно проверяйте заголовки с помощью автоматических сканеров по мере изменения зависимостей вашего сайта
  • На нашем опыте удобнее всего запускать такой сканер прямо в CI/CD-пайплайне — регрессии выявляются до попадания изменений в продакшен

Распространённые ошибки при настройке заголовков безопасности

ОшибкаПоследствиеИсправление
Использование 'unsafe-inline' + 'unsafe-eval' в CSPНейтрализует защиту от XSSИспользуйте nonce или хэши вместо этого
Отсутствие ключевого слова always в NginxЗаголовки отсутствуют на страницах ошибокДобавьте always к каждому add_header
HSTS без полного покрытия HTTPSПоддомены становятся недоступнымиСначала убедитесь, что все поддомены имеют действительные TLS-сертификаты
Забытый frame-ancestors в CSPКликджекинг по-прежнему возможенДобавьте frame-ancestors 'none' в CSP
Установка Referrer-Policy: unsafe-urlПолный URL утекает к третьим сторонамИспользуйте strict-origin-when-cross-origin

Инструменты проверки HTTP Security Headers

Просканируйте заголовки безопасности вашего сайта:

🔧 Security Header Scanner — проанализируйте все заголовки безопасности и получите практический отчёт с оценками.

Ссылки

  • 📄 MDN — Content Security Policy (CSP)
  • 📄 MDN — Strict-Transport-Security
  • 📄 MDN — Permissions-Policy
  • 📄 OWASP Secure Headers Project
  • 📄 OWASP HTTP Headers Cheat Sheet
  • 📄 MDN — Referrer-Policy

🎯 Ключевой вывод: заголовки безопасности — это бесплатные, высокоэффективные средства защиты. Как минимум разверните CSP, HSTS, X-Frame-Options, X-Content-Type-Options, Referrer-Policy и Permissions-Policy. Начните с CSP в режиме report-only, итерируйте на основе реальных отчётов о нарушениях, затем включите принудительное применение. Сочетайте это с регулярным сканированием, чтобы выявлять регрессии по мере изменения сторонних зависимостей.

Ответы на эти вопросы могут быть для вас полезными

Можно ли сломать сайт, включив заголовки безопасности?

Да, если не тестировать предварительно. Слишком строгий CSP заблокирует легитимные скрипты и стили. Именно поэтому рекомендуется начинать с режима Content-Security-Policy-Report-Only и анализировать отчёты о нарушениях перед включением принудительного применения.

Что делать, если на сайте используются сторонние скрипты — аналитика, чаты, рекламные сети?

Добавьте домены этих сервисов в соответствующие директивы CSP: например, script-src 'self' https://www.googletagmanager.com. Используйте режим report-only для выявления всех необходимых источников до перехода в боевой режим.

Нужно ли указывать always в конфигурации Nginx?

Обязательно. Без ключевого слова always заголовки отправляются только при кодах ответа 2xx. Страницы ошибок (404, 500 и другие) останутся без защиты, что создаёт уязвимость именно там, где пользователь может видеть чужой контент.

Чем frame-ancestors в CSP отличается от X-Frame-Options?

frame-ancestors — более современный механизм с поддержкой нескольких источников и гибкими правилами. X-Frame-Options поддерживается старыми браузерами, но не позволяет задавать список разрешённых доменов. Рекомендуется использовать оба заголовка одновременно для максимальной совместимости.

Как часто нужно пересматривать конфигурацию заголовков безопасности?

При каждом значимом изменении зависимостей: подключении нового CDN, сторонней библиотеки или виджета. Автоматический сканер, запускаемый в CI/CD-пайплайне, позволяет выявлять регрессии до попадания изменений в продакшен.

Оцените статью
0 0 голоса
Рейтинг статьи
Подписаться
Уведомить о
guest

0 комментариев
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии
0
Оставьте комментарий! Напишите, что думаете по поводу статьи.x