Я Максим, веб-разработчик. Большинство сайтов, которые я аудирую, не имеют даже базовых заголовков безопасности. Владелец сайта об этом не знает, разработчик «забыл» или не посчитал нужным. А ведь настройка занимает пятнадцать-двадцать минут и закрывает целый класс серьёзных атак: XSS (межсайтовый скриптинг), кликджекинг, подмена контента, перехват данных. Разбираю каждый заголовок подробно: что он делает, зачем нужен, как настроить и какие подводные камни существуют.

Почему заголовки безопасности — это не паранойя

Когда браузер загружает ваш сайт, он выполняет код, загружает ресурсы и принимает решения о доверии. HTTP-заголовки безопасности — это инструкции для браузера: что разрешено, что запрещено, как себя вести в определённых ситуациях. Без этих инструкций браузер действует по умолчанию — а значения по умолчанию разработаны для максимальной совместимости, а не для максимальной безопасности.

Представьте: злоумышленник нашёл уязвимость в форме комментариев на вашем сайте и внедрил вредоносный JavaScript-код. Без заголовка Content-Security-Policy этот код выполнится в браузере каждого посетителя — может украсть cookies, перенаправить на фишинговую страницу, показать фальшивую форму оплаты. С правильно настроенным CSP браузер просто заблокирует выполнение стороннего скрипта, и атака провалится.

Я проверяю заголовки безопасности на каждом аудите через сервис securityheaders.com. Результат: примерно 70% коммерческих сайтов получают оценку D или F. После настройки шести основных заголовков оценка поднимается до A или A+. Двадцать минут работы — и ваш сайт из категории «без защиты» переходит в категорию «профессионально защищён».

Content-Security-Policy (CSP) — главный щит

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

Базовая идея: разрешить загрузку только со своего домена и явно указанных доверенных источников. Всё остальное — запретить. Если злоумышленник внедрит скрипт с неизвестного домена — CSP не даст ему выполниться.

Но вот в чём сложность: на типичном коммерческом сайте используются десятки внешних ресурсов. Яндекс Метрика загружает скрипты с mc.yandex.ru. Виджет чата — с cdn.jivo.ru. Шрифты — с fonts.googleapis.com. Карта — с api-maps.yandex.ru. Каждый из этих источников нужно явно разрешить в CSP. Если забудете хоть один — соответствующий функционал перестанет работать.

Поэтому я никогда не включаю CSP «на боевом» без тестирования. Начинаю с режима Content-Security-Policy-Report-Only — он не блокирует ресурсы, а только логирует нарушения. Открываю сайт, прохожу по всем страницам, проверяю консоль браузера — вижу, какие ресурсы загружаются и с каких доменов. На основе этих данных формирую белый список. И только после полного тестирования переключаю на блокирующий режим.

Процесс кажется сложным, но результат стоит усилий. CSP — это единственный заголовок, который реально защищает от XSS-атак, а XSS — самый распространённый тип веб-уязвимостей в мире.

X-Frame-Options — защита от кликджекинга

Этот заголовок запрещает загрузку вашего сайта во фрейме (iframe) на чужом домене. Защищает от кликджекинга — атаки, при которой злоумышленник размещает ваш сайт в невидимом iframe поверх своей страницы. Пользователь думает, что кликает по безобидным элементам на сайте злоумышленника, а на самом деле нажимает кнопки на вашем сайте — например, «Подтвердить перевод» или «Удалить аккаунт».

Два основных значения: DENY (запретить встраивание всем, включая свой домен) и SAMEORIGIN (разрешить встраивание только на страницах своего домена). Для большинства сайтов подходит DENY. Исключение — если у вас есть легитимная необходимость встраивать свой сайт в iframe на своих же страницах (например, конструктор или предпросмотр).

Настройка — одна строка в конфиге сервера. Побочных эффектов при DENY практически не бывает, если только сторонние сервисы не встраивают ваш сайт во фрейм по вашему запросу.

X-Content-Type-Options — запрет на угадывание типа контента

Заголовок X-Content-Type-Options: nosniff запрещает браузеру «угадывать» MIME-тип файла. Без этого заголовка браузер может интерпретировать текстовый файл как JavaScript и выполнить его — это реальный вектор атаки, называемый MIME-sniffing.

Представьте: злоумышленник загружает на ваш сайт файл с расширением .txt, содержащий JavaScript-код. Без nosniff браузер может решить: «Выглядит как скрипт, запущу-ка его». С nosniff браузер строго следует указанному Content-Type и не выполняет файл, если он объявлен как текст.

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

Strict-Transport-Security (HSTS) — принудительный HTTPS

HSTS говорит браузеру: «Всегда используй HTTPS для этого домена, даже если пользователь ввёл HTTP в адресной строке или кликнул по HTTP-ссылке». После первого визита по HTTPS браузер запоминает это правило на указанный срок и автоматически перенаправляет все запросы на HTTPS.

Зачем это нужно, если у вас и так есть редирект с HTTP на HTTPS? Редирект происходит на сервере — а значит, первый запрос всё равно идёт по незащищённому HTTP. В этот момент атакующий в той же Wi-Fi-сети может перехватить трафик (man-in-the-middle). HSTS устраняет эту уязвимость: после первого визита браузер даже не пытается обращаться по HTTP.

Рекомендуемая настройка: Strict-Transport-Security: max-age=31536000; includeSubDomains — запоминать на год, включая все поддомены. Важная оговорка: включайте HSTS только после того, как убедились, что HTTPS работает корректно на всём сайте и всех поддоменах. Если что-то сломается — пользователи не смогут зайти по HTTP, а отменить HSTS на стороне браузера нельзя (кроме ожидания истечения max-age).

Referrer-Policy — контроль утечки URL

Когда пользователь переходит с вашего сайта на другой, браузер передаёт заголовок Referer, содержащий адрес предыдущей страницы. Проблема: если URL содержит конфиденциальные данные (токен авторизации в параметрах, номер заказа, внутренний идентификатор), эта информация утекает стороннему сайту.

Referrer-Policy: strict-origin-when-cross-origin — оптимальное значение для большинства сайтов. При переходе на внешний сайт передаётся только домен (https://site.ru), а не полный URL. При переходах внутри своего сайта — полный URL сохраняется.

Permissions-Policy — ограничение доступа к API устройства

Современные браузеры предоставляют веб-страницам доступ к камере, микрофону, геолокации, акселерометру, автовоспроизведению видео. Permissions-Policy позволяет явно указать, какие из этих возможностей доступны на вашем сайте.

Пример: Permissions-Policy: camera=(), microphone=(), geolocation=(self) — запретить доступ к камере и микрофону для всех (включая встроенные iframe), разрешить геолокацию только своему домену. Если злоумышленник внедрит iframe с запросом на доступ к камере — браузер автоматически откажет.

Как проверить заголовки на своём сайте

Самый быстрый способ — сервис securityheaders.com. Вводите URL, получаете оценку от A+ до F с подробным описанием каждого заголовка. Альтернатива — открыть DevTools в Chrome (F12), вкладка Network, кликнуть по основному запросу и посмотреть Response Headers.

Где и как настраивать

Конкретная реализация зависит от вашего стека. На Nginx — директивы add_header в конфигурации сервера или конкретного location-блока. На Apache — директивы Header в .htaccess или конфигурации виртуального хоста. На Vercel — файл vercel.json с секцией headers или middleware на Next.js. На Cloudflare — через Transform Rules или Cloudflare Workers для полного контроля.

Важный нюанс: некоторые хостинги не дают прямого доступа к конфигурации сервера. В этом случае можно попробовать настроить заголовки через .htaccess (если Apache) или через плагины CMS. На WordPress есть плагины вроде Headers Security Advanced & HSTS WP. Но я всегда предпочитаю настройку на уровне сервера — это надёжнее и быстрее.

Пятнадцать-двадцать минут работы — и ваш сайт защищён от основных типов веб-атак. Это тот случай, когда минимальные усилия дают максимальный эффект для безопасности. Не откладывайте — проверьте свой сайт прямо сейчас.