HTTP-заголовки безопасности: настройка CSP, HSTS, X-Content-Type-Options на Nginx
Исчерпывающее руководство по настройке HTTP-заголовков безопасности в Nginx. Готовые конфигурации Content-Security-Policy (CSP), Strict-Transport-Security (HSTS), защиты от кликджекинга и сниффинга MIME.
HTTP-заголовки безопасности — это стандартизированные директивы в ответе веб-сервера, которые сообщают браузеру пользователя строгие правила обработки контента, исполнения скриптов и ограничения сетевых запросов. Будучи настроенными один раз, они создают мощнейший рубеж защиты с нулевыми накладными расходами на производительность, предотвращая атаки XSS, Clickjacking, MIME-sniffing и перехват незашифрованного трафика.
Несмотря на критическую важность, более 65% коммерческих сайтов проваливают аудит заголовков безопасности. Причина проста: настройка политик вроде Content-Security-Policy (CSP) требует внимательности, чтобы случайно не заблокировать работу легитимных счетчиков аналитики, шрифтов или скриптов онлайн-чата.
1. Content-Security-Policy (CSP): главный щит против XSS и инъекций
Content-Security-Policy (CSP) — ключевой инструмент защиты от межсайтового скриптинга (XSS). Он задает браузеру белый список доверенных источников, с которых разрешено загружать скрипты, стили, изображения и фреймы. Вредоносный скрипт, внедренный злоумышленником через комментарий или параметр ссылки, будет заблокирован браузером при попытке исполнения.
# Строгая проверенная политика Content-Security-Policy для Nginx
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' https:; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' data:; connect-src 'self' https:; object-src 'none'; frame-ancestors 'none'; base-uri 'self'; form-action 'self';" always;
2. HTTP Strict Transport Security (HSTS): принудительный переход на HTTPS
Заголовок Strict-Transport-Security (HSTS) указывает браузеру открывать сайт исключительно по зашифрованному протоколу HTTPS в течение заданного срока. Это ликвидирует окно уязвимости при первоначальном обращении по незащищенному HTTP, исключая атаки типа SSL Stripping.
# Принудительный HSTS на 2 года с поддоменами и включением в preload-список
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
3. Защита от кликджекинга: X-Frame-Options и frame-ancestors
Атака Clickjacking заключается в незаметном встраивании вашего сайта в прозрачный <iframe> на вредоносном ресурсе. Пользователь думает, что кликает по кнопке в игре, а на самом деле подтверждает перевод денег или удаление профиля на вашем сервисе. Директивы X-Frame-Options: DENY и CSP frame-ancestors 'none' полностью запрещают встраивание во фреймы.
add_header X-Frame-Options "DENY" always;
4. Запрет подмены MIME-типов: X-Content-Type-Options: nosniff
Исторически браузеры пытались угадать формат файла независимо от заголовка Content-Type (MIME sniffing). Злоумышленник мог загрузить вредоносный JavaScript под видом аватарки с расширением .jpg, и браузер исполнял его как скрипт. Флаг nosniff обязывает браузер строго доверять объявленному серверному типу контента.
add_header X-Content-Type-Options "nosniff" always;
5. Готовый production-конфиг заголовков безопасности для Nginx
Соберите все рекомендованные директивы в отдельный файл сниппета, который можно легко подключать директивой include во всех блоках server вашего веб-сервера.
# /etc/nginx/snippets/security-headers.conf
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;
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' https:; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' data:; connect-src 'self' https:; object-src 'none'; frame-ancestors 'none';" always;
Чек-лист безопасности для разработчика
- ✓ Включить Strict-Transport-Security (HSTS) со сроком не менее 1 года и флагом preload
- ✓ Настроить базовую политику Content-Security-Policy (CSP) для скриптов и объектов
- ✓ Добавить заголовок X-Content-Type-Options: nosniff против атак подмены MIME
- ✓ Установить X-Frame-Options: DENY или CSP frame-ancestors для защиты от кликджекинга
- ✓ Настроить Referrer-Policy: strict-origin-when-cross-origin
- ✓ Проверить итоговые заголовки в сканере Site Check на отсутствие регрессий
Резюме и ключевые выводы аудитора безопасности
При запуске веб-сервисов и приложений на базе современных фреймворков (Next.js, Astro, React, Supabase) безопасность периметра не должна быть второстепенным этапом. Более 85% утечек конфиденциальных данных и взломов баз данных происходят не из-за изощрённых уязвимостей нулевого дня (0-day), а по причине тривиальных ошибок конфигурации: забытых тестовых эндпоинтов, открытых файлов окружения, некорректных правил CORS и отсутствия строгих политик разграничения доступа (RLS).
Регулярный превентивный аудит внешнего контура с помощью Site Check позволяет обнаружить опасные сигнатуры за считанные секунды и закрыть векторы атак до того, как они попадут в поле зрения автоматизированных ботнетов.