Назад в блог

Security headers: HSTS, CSP, X-Frame-Options и другие

· 7 мин чтения

Кратко: Security HTTP-заголовки - это строки, которые сервер добавляет к каждому HTTP-ответу, чтобы сказать браузеру, как обращаться с вашим сайтом. Правильно настроенные устраняют целые классы атак (XSS, clickjacking, MITM) - и они бесплатны.

Кратко: Security HTTP-заголовки - это строки, которые сервер добавляет к каждому HTTP-ответу, чтобы сказать браузеру, как обращаться с вашим сайтом. Правильно настроенные устраняют целые классы атак (XSS, clickjacking, MITM) - и они бесплатны.

Почему они важны

Приложение может быть идеально защищено backend-side, но без правильных заголовков всё ещё уязвимо для browser-side атак: cross-site scripting (XSS), clickjacking, protocol downgrade, MIME confusion. Security-заголовки переносят защиту в браузер.

Strict-Transport-Security (HSTS)

Заставляет HTTPS для всех будущих посещений. После первого HTTPS-визита браузер запоминает домен и сам переписывает любую http://-ссылку в https://, даже если пользователь кликнет на плохой ответ.

Strict-Transport-Security: max-age=63072000; includeSubDomains; preload
  • max-age=63072000 = действует 2 года
  • includeSubDomains = правило действует и для всех поддоменов (внимание: если у вас HTTP-only поддомен, сломает его)
  • preload = позволяет включение в HSTS preload список, встроенный в Chrome / Firefox / Safari

Внимание: HSTS с preload удаляется из списка 6+ месяцев. Не включайте preload до того, как проверите, что HTTPS работает стабильно и для всех поддоменов.

Content-Security-Policy (CSP)

Самый мощный, но и самый сложный для настройки заголовок. Whitelist того, откуда браузер может загружать скрипты, стили, изображения, iframe-ы. Без CSP атакующий, способный инжектировать <script> тэг, может выполнить любой JS - с CSP только код из одобренных источников.

Content-Security-Policy: default-src 'self'; script-src 'self' 'sha256-...'; img-src 'self' data: https://cdn.example.com; style-src 'self' 'unsafe-inline'; frame-ancestors 'none'

Обычные директивы:

  • default-src 'self' = по умолчанию разрешать только ресурсы из моего домена
  • script-src = JS-источники (укажите hash или nonce для inline-скриптов)
  • style-src = CSS-источники
  • img-src = изображения
  • connect-src = AJAX, WebSocket, EventSource
  • frame-ancestors 'none' = никто не может встроить страницу в iframe (лучше, чем X-Frame-Options)
  • report-uri /csp-report = браузер отправляет JSON при каждом нарушении (вы ловите в backend и логируете)

X-Frame-Options

Более старая альтернатива frame-ancestors. Защищает от clickjacking - атакующий вставляет вашу страницу как iframe и перекрывает невидимыми кнопками.

X-Frame-Options: DENY

Значения: DENY (никто), SAMEORIGIN (только мой домен), ALLOW-FROM uri (deprecated).

X-Content-Type-Options

X-Content-Type-Options: nosniff

Отключает MIME sniffing - браузер будет уважать Content-Type, который вернул сервер. Без этого атакующий может загрузить файл с неправильным типом (например, изображение, которое на самом деле HTML со скриптом) и браузер может выполнить как web page.

Referrer-Policy

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

Управляет, сколько информации о предыдущей странице браузер отправляет в Referer заголовке при клике. Default в современных браузерах уже strict-origin-when-cross-origin, но явный декларативный заголовок обеспечивает консистентность.

Permissions-Policy

Отключает API, которые вам не нужны - камеру, микрофон, GPS, geolocation. Атакующий через XSS не может запросить эти API.

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

Практическая конфигурация в nginx

server {
  listen 443 ssl http2;
  server_name example.com;

  add_header Strict-Transport-Security "max-age=63072000; includeSubDomains" always;
  add_header X-Content-Type-Options "nosniff" always;
  add_header X-Frame-Options "DENY" always;
  add_header Referrer-Policy "strict-origin-when-cross-origin" always;
  add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always;

  # CSP обширный - определяйте согласно вашему приложению
  add_header Content-Security-Policy "default-src 'self'; script-src 'self'; ..." always;
}

Ключ - always - без него nginx пропускает заголовки при error response (4xx, 5xx).

Аудит текущего состояния

Проще всего через online tool. Наш header check покажет вам, какие заголовки отсутствуют и какие неправильны. Для тщательного аудита и securityheaders.com даёт A-F оценку.

Вывод

Security-заголовки - одна из лучших инвестиций по соотношению усилие к выгоде в области security - обычно полчаса настройки в reverse proxy против целой категории browser-side атак. Аудит раз в полгода в рамках регулярного обслуживания - разумный минимум.

Бесплатный аудит security headers

Без регистрации, результат за три секунды.

Протестировать сайт →


Попробуйте ePulz.io бесплатно - 7 дней без банковской карты.

Создать аккаунт