Назад к блогу

HTTP Security Headers: полный гид по CSP, HSTS, X-Frame-Options

15 мин. чтения0 просмотровРуководства

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

HTTP-заголовки безопасности — это инструкции, которые сервер отправляет браузеру вместе с веб-страницей. Они указывают браузеру, как обрабатывать контент, какие ресурсы загружать и какие функции отключить.

Правильно настроенные заголовки:

  • Защищают от XSS — предотвращают выполнение вредоносных скриптов
  • Предотвращают clickjacking — запрещают встраивание сайта в iframe
  • Обеспечивают HTTPS — принудительное шифрование
  • Контролируют ресурсы — ограничивают загрузку сторонних скриптов
  • Защищают приватность — контролируют утечку информации через referrer

Большинство сайтов не настраивают все основные заголовки безопасности корректно.

Content-Security-Policy (CSP)

Что делает

CSP — самый мощный заголовок безопасности. Определяет, откуда браузер может загружать ресурсы: скрипты, стили, изображения, шрифты, фреймы.

Почему критически важен

CSP — главная защита от XSS-атак. Даже если злоумышленник внедрит скрипт, CSP не позволит его выполнить, если источник не в белом списке.

Основные директивы

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';
  connect-src 'self' https://api.example.com;
  frame-ancestors 'none';
  base-uri 'self';
  form-action 'self'
  • default-src 'self' — по умолчанию только со своего домена
  • script-src 'self' https://cdn.example.com — скрипты со своего домена и CDN
  • style-src 'self' 'unsafe-inline' — стили со своего домена и inline
  • img-src 'self' data: https: — изображения со своего домена и любые HTTPS
  • frame-ancestors 'none' — запрет встраивания в iframe
  • base-uri 'self' — защита от base tag injection
  • form-action 'self' — формы отправляются только на свой домен

Пошаговое внедрение

Шаг 1: Report-Only — начните с Content-Security-Policy-Report-Only, который не блокирует, а логирует нарушения.

Шаг 2: Анализ отчётов — соберите данные о загружаемых ресурсах.

Шаг 3: Enforcement — переключитесь на блокирующий режим.

Типичные ошибки

  • unsafe-inline в script-src — обнуляет защиту от XSS
  • unsafe-eval — позволяет выполнять строки как код
  • Слишком широкие источники (*, https:) — ослабляют политику
  • Отсутствие default-src — ресурсы без директивы не ограничены

Настройка nginx

add_header Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; frame-ancestors 'none'" always;

Настройка Apache

Header always set Content-Security-Policy "default-src 'self'; frame-ancestors 'none'"

Strict-Transport-Security (HSTS)

Что делает

HSTS указывает браузеру всегда использовать HTTPS. После получения заголовка браузер автоматически перенаправляет HTTP на HTTPS.

Почему важен

Защищает от:

  • SSL Stripping — перехват первого HTTP-запроса
  • Случайного перехода на HTTP — клик на старую ссылку
  • Mixed Content — загрузка HTTP-ресурсов на HTTPS-странице

Рекомендуемая конфигурация

Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
  • max-age=31536000 — запомнить на 1 год
  • includeSubDomains — распространить на поддомены
  • preload — заявка на HSTS Preload List

HSTS Preload List

Браузеры Chrome, Firefox, Safari и Edge поддерживают Preload List — HSTS работает ещё до первого посещения. Подать заявку: hstspreload.org

Настройка nginx

add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;

X-Frame-Options

Что делает

Управляет встраиванием страницы в <iframe>, <frame>, <embed>, <object>.

Почему важен

Защищает от clickjacking — ваш сайт в невидимом iframe, пользователь нажимает на кнопки, не видя их.

Значения

  • DENY — полный запрет
  • SAMEORIGIN — только со своего домена
X-Frame-Options: DENY

Примечание: CSP frame-ancestors — современная замена. Используйте оба для совместимости.

X-Content-Type-Options

Что делает

Запрещает MIME sniffing — браузер использует только тип, указанный сервером.

Почему важен

Без него браузер может интерпретировать файл как скрипт. Это путь для XSS через загрузку файлов.

X-Content-Type-Options: nosniff

Referrer-Policy

Что делает

Контролирует информацию о URL при переходе на другой сайт.

Почему важен

URL могут содержать токены сброса пароля, session ID, внутренние пути. Без контроля они утекают к сторонним сайтам.

Рекомендуемые значения

  • strict-origin-when-cross-origin — при переходе на другой сайт только origin, внутри сайта — полный URL
  • no-referrer — никогда не передавать
  • same-origin — только внутри сайта
Referrer-Policy: strict-origin-when-cross-origin

Permissions-Policy

Что делает

Контролирует API браузера: камера, микрофон, геолокация, платежи.

Почему важен

Ограничивает доступ к чувствительным API от сторонних скриптов и iframe.

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

Пустые скобки () означают полный запрет.

Полная конфигурация nginx

server {
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
    add_header Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; frame-ancestors 'none'; base-uri 'self'" 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=(), payment=()" always;
}

Полная конфигурация Apache

<IfModule mod_headers.c>
    Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
    Header always set Content-Security-Policy "default-src 'self'; frame-ancestors 'none'"
    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=()"
</IfModule>

Проверка заголовков

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

  1. DevTools — вкладка Network, Response Headers
  2. curlcurl -I https://example.com
  3. ОнлайнПроверка заголовков Периметра покажет наличие всех заголовков и оценит конфигурацию

Частые ошибки

1. Заголовки только для HTML

Настройте заголовки глобально (always в nginx), включая API-ответы.

2. Конфликт location-блоков

В nginx заголовки в location переопределяют server. Дублируйте заголовки в каждом location.

3. CSP ломает функциональность

Начинайте с Report-Only, тестируйте на staging.

4. Слишком мягкие политики

CSP с unsafe-inline unsafe-eval * бесполезен. Начните строго и ослабляйте по необходимости.

Что настроить в первую очередь

HTTP-заголовки безопасности — простая и эффективная мера защиты. Настройка занимает минуты, защита работает для всех пользователей.

Минимальный набор:

  • HSTS — принудительный HTTPS
  • CSP — защита от XSS
  • X-Frame-Options — защита от clickjacking
  • X-Content-Type-Options — защита от MIME sniffing
  • Referrer-Policy — контроль утечки URL

Проверьте заголовки вашего сайта: perimeter-scan.ru/tools/headers-check

Поделиться:TelegramVK

Похожие статьи

Мы используем файлы cookie для обеспечения работоспособности сервиса и улучшения качества обслуживания. Продолжая использовать сайт, вы соглашаетесь с политикой конфиденциальности.