Перейти к содержимому
🔒 HTTP Security Headers для WordPress: полный гайд по настройке

🔒 HTTP Security Headers для WordPress: полный гайд по настройке

Сайт на WordPress работает, плагин безопасности установлен, но проверка на securityheaders.com выдаёт оценку F. Знакомо?

HTTP-заголовки безопасности — это невидимый слой защиты, о котором забывают даже после настройки файрвола и двухфакторной аутентификации. Они не требуют продления лицензии, не грузят сервер и закрывают целые классы атак: от кликджекинга до перехвата сессий. И добавляются за 10 минут.

Ниже, пошагово: какие заголовки действительно нужны, как их настроить через.htaccess, functions.php или плагин, и как проверить, что защита работает, а не просто числится.

💡 Быстрый обзор:

  • Проверьте текущие заголовки сайта через securityheaders.com или Mozilla Observatory, увидите реальную картину
  • Включите базовый набор из 4-5 заголовков: X-Content-Type-Options, X-Frame-Options, HSTS, Referrer-Policy, Permissions-Policy
  • Выберите способ: пара строк в.htaccess (Apache/LiteSpeed), сниппет в functions.php или плагин Headers Security Advanced & HSTS WP
  • CSP оставляйте на потом, сложный в настройке и ломает Gutenberg, если сделан без тестирования
  • После внедрения пройдите повторную проверку, оценка A+ достижима за 10 минут

Что такое HTTP Security Headers

Когда браузер запрашивает страницу, веб-сервер отдаёт не только HTML-код. Каждый HTTP-ответ содержит служебные поля, заголовки. Часть из них отвечает за кеширование и тип контента, а часть, за безопасность.

Браузер читает security-заголовки ещё до того, как начнёт рендерить страницу. Если сервер говорит «запрещаю встраивать этот сайт во фреймы», браузер не станет этого делать, даже если в коде страницы прописан <iframe>. Если сервер говорит «год работаем только по HTTPS», браузер запомнит и не пойдёт на HTTP-версию, даже если пользователь вручную её наберёт.

Никакой JavaScript, никакой плагин, никакой файрвол на это не влияют. Это уровень протокола. Именно поэтому заголовки, отдельный, самостоятельный рубеж защиты.

Зачем это WordPress-сайту

Плагины безопасности вроде Wordfence или Solid Security закрывают уязвимости на уровне приложения: брутфорс, инъекции, вредоносные загрузки. HTTP-заголовки работают на уровень выше, они защищают сам канал связи между сервером и посетителем.

Вот что закрывают правильно настроенные заголовки:

  • Кликджекинг. Злоумышленник встраивает ваш сайт в прозрачный фрейм поверх своего и перехватывает клики пользователя. Закрывается заголовком X-Frame-Options или директивой frame-ancestors в CSP.

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

  • Перехват сессии. Злоумышленник на открытом Wi-Fi подменяет ответ сервера и крадёт cookie входа. HSTS запрещает браузеру ходить на HTTP-версию сайта.

  • Утечка реферера. При переходе по внешней ссылке сайт-назначение видит, с какой страницы пришёл пользователь, включая URL с параметрами. Referrer-Policy это ограничивает.

  • Несанкционированный доступ к устройствам. Веб-страница запрашивает микрофон, камеру или геолокацию без ведома пользователя. Permissions-Policy запрещает такие запросы на уровне браузера.

CSP добавляет ещё один слой: вы точно задаёте, с каких доменов можно грузить скрипты, стили и шрифты. Даже если вредоносный код попал в базу данных, браузер не выполнит его, потому что источник не в белом списке. Но CSP требует аккуратности: чуть ошибётесь, и редактор Gutenberg перестанет работать.

Ключевые HTTP-заголовки безопасности: что включает и зачем

Ниже, заголовки, которые имеет смысл настраивать на любом WordPress-сайте. Для каждого указано: от какой атаки защищает, рекомендуемое значение и где может сломаться.

X-Content-Type-Options

Самый простой и безопасный в настройке. Единственное допустимое значение, nosniff. Браузер перестаёт «угадывать» MIME-тип файла по содержимому и доверяет только тому типу, который передал сервер в заголовке Content-Type.

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

Рекомендуемое значение: nosniff

Риски поломок: минимальны. Проблемы возможны только если сервер отдаёт файлы с неправильным Content-Type, но это отдельная проблема, которую стоит исправить, а не маскировать.

X-Frame-Options

Контролирует, может ли ваш сайт быть встроен в <frame>, <iframe> или <object> на чужом сайте.

Два основных значения:

  • DENY, полный запрет встраивания. Максимальная защита.
  • SAMEORIGIN, разрешено встраивание только с того же домена. Нужно, если вы сами используете фреймы для своих же страниц (например, предпросмотр в админке).

Для большинства WordPress-сайтов подходит SAMEORIGIN. Если вы точно знаете, что никакие фреймы не используются, ставьте DENY.

Рекомендуемое значение: SAMEORIGIN

Риски поломок: некоторые плагины используют iframe для предпросмотра. Если после включения DENY что-то перестало отображаться в админке, переключитесь на SAMEORIGIN.

Strict-Transport-Security (HSTS)

Говорит браузеру: «ближайшие N секунд ходи на этот домен только по HTTPS». Защищает от downgrade-атак и перехвата cookie на открытых сетях.

Ключевой параметр, max-age. Рекомендуется начинать с небольшого значения (сутки или неделя) и после проверки увеличивать до года.

Опциональный параметр includeSubDomains распространяет правило на все поддомены, важно, если у вас их несколько и вы используете CDN.

Параметр preload включает сайт в глобальный HSTS-список браузеров: Chrome, Firefox и Safari будут ходить на ваш домен только по HTTPS ещё до первого запроса. Подача заявки, через hstspreload.org.

Рекомендуемое значение: max-age=31536000; includeSubDomains

Риски поломок: если включить HSTS, а SSL-сертификат истечёт, пользователи вообще не попадут на сайт. Следите за автообновлением сертификата.

Referrer-Policy

Управляет тем, какую информацию о странице-источнике браузер передаёт при переходе по ссылке на другой сайт.

Основные значения, от самого строгого к самому мягкому:

  • no-referrer, вообще ничего не передаётся.
  • strict-origin-when-cross-origin, на другой домен передаётся только домен (без пути и параметров); на свой, полный URL. Оптимальный баланс приватности и аналитики.
  • strict-origin, всегда только домен, без пути.

Если вы вообще не хотите, чтобы сайты-назначения знали, откуда пришёл пользователь, ставьте no-referrer. Но имейте в виду: вы потеряете реферальный трафик в своей же аналитике.

Рекомендуемое значение: strict-origin-when-cross-origin

Риски поломок: минимальны. Некоторые сторонние сервисы могут требовать реферер для работы (например, шлюзы оплаты с проверкой источника). Отследить такие случаи можно через консоль браузера.

Permissions-Policy

Раньше назывался Feature-Policy. Ограничивает доступ веб-страницы к «железным» API браузера: микрофону, камере, геолокации, USB, платежным API и так далее.

Формат: название-фичи=(разрешённый-источник). Например:

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

Этот пример полностью запрещает доступ к камере и микрофону для всех источников, а геолокацию разрешает только для самого сайта (self).

Полный список фич, на MDN. Для WordPress-сайта без видеочатов и PWA-функций достаточно закрыть камеру, микрофон и геолокацию, остальное опционально.

Рекомендуемое значение: зависит от функционала сайта. Минимум, camera=(), microphone=(), geolocation=(self).

Риски поломок: если на сайте есть функционал видеозвонков, PWA или WebUSB, проверьте, какие фичи ему нужны, и не закрывайте их.

Content-Security-Policy (CSP)

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

Пример минимальной политики для WordPress:

1Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:;
2

*Почему unsafe-inline и unsafe-eval:* WordPress, Gutenberg и десятки плагинов генерируют inline-скрипты и используют eval(). Без этих директив админка просто перестанет работать. Это плата за совместимость.

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

Риски поломок: высокие. Ошибка в CSP может полностью сломать фронтенд и админку. Всегда тестируйте на стейдже или через Report-Only.

Как проверить текущие заголовки сайта

Перед настройкой, аудит. Три инструмента, от простого к детальному:

  • securityheaders.com, вводите URL и получаете оценку от A+ до F с расшифровкой по каждому заголовку. Бесплатно, без регистрации.

  • Mozilla Observatory, более детальный аудит: оценивает не только заголовки, но и TLS-настройки, cookie-атрибуты, CORS и другие аспекты. Тоже бесплатно.

  • Chrome DevTools, откройте вкладку Network, выберите любой запрос к вашему сайту и посмотрите секцию Response Headers. Быстрый способ проверить, «взлетели» ли изменения после правки.htaccess.

Проверьте сайт прямо сейчас. Если оценка ниже B, у вас нет даже базовых заголовков, и треть пунктов ниже вы поставите за 5 минут.

Способы настройки HTTP-заголовков в WordPress

Три пути, от ручного к автоматическому. Выбирайте под свою ситуацию.

Способ 1: Через.htaccess (Apache/LiteSpeed)

Самый быстрый способ для сайтов на Apache или LiteSpeed. Добавьте в .htaccess в корне сайта (перед # BEGIN WordPress):

1<IfModule mod_headers.c>
2 Header set X-Content-Type-Options "nosniff"
3 Header set X-Frame-Options "SAMEORIGIN"
4 Header set Strict-Transport-Security "max-age=31536000; includeSubDomains"
5 Header set Referrer-Policy "strict-origin-when-cross-origin"
6 Header set Permissions-Policy "camera=(), microphone=(), geolocation=(self)"
7</IfModule>

Оболочка <IfModule mod_headers.c> гарантирует, что сайт не упадёт с ошибкой 500, если модуль mod_headers не включён. Если вы точно знаете, что он активен, можно без неё.

После сохранения выполните в терминале (если есть WP-CLI) или просто откройте сайт и проверьте заголовки через securityheaders.com. Изменения в .htaccess применяются мгновенно, перезагрузка сервера не нужна.

Способ 2: Через functions.php (Nginx / универсальный)

Работает независимо от веб-сервера, подходит и для Nginx, и для Apache. Добавьте в functions.php дочерней темы или через плагин Code Snippets:

1function sdstudio_add_security_headers() {
2 header( 'X-Content-Type-Options: nosniff' );
3 header( 'X-Frame-Options: SAMEORIGIN' );
4 header( 'Strict-Transport-Security: max-age=31536000; includeSubDomains' );
5 header( 'Referrer-Policy: strict-origin-when-cross-origin' );
6 header( 'Permissions-Policy: camera=(), microphone=(), geolocation=(self)' );
7}
8add_action( 'send_headers', 'sdstudio_add_security_headers' );

Хук send_headers срабатывает раньше, чем WordPress начнёт отдавать контент, заголовки уходят в самом первом ответе сервера.

Для Nginx этот способ предпочтительнее, чем лезть в конфигурацию сервера (особенно на shared-хостинге, где доступа к nginx.conf часто нет). Минус, заголовки работают только для PHP-запросов, проходящих через WordPress. Статические файлы (изображения, CSS, JS) обслуживаются Nginx напрямую и заголовков не получат. Для них потребуется конфигурация на уровне сервера.

Способ 3: Через плагин Headers Security Advanced & HSTS WP

Если не хотите трогать код, используйте специальный плагин. Headers Security Advanced & HSTS WP собирает все security-заголовки в одном интерфейсе и включает их одной кнопкой.

Плагин ставит предустановленные значения для всех ключевых заголовков сразу после активации, X-Content-Type-Options, X-Frame-Options, HSTS, CSP, Referrer-Policy, Permissions-Policy и ряд дополнительных (CORP, COOP, COEP). Каждый заголовок можно отключить или перенастроить под себя.

Плюс подхода: плагин не зависит от веб-сервера и работает одинаково на Apache, Nginx, LiteSpeed и IIS. При деактивации возвращает конфигурацию сайта в исходное состояние.

Альтернатива: Redirection

Плагин Redirection известен как менеджер редиректов, но умеет и добавлять HTTP-заголовки. После установки и базовой настройки перейдите в раздел Site → Headers, интерфейс позволяет прописать любые пары «заголовок: значение».

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

На видео, наглядная демонстрация настройки заголовков через плагин Headers Security Advanced: от установки до проверки результата на securityheaders.com.

⁉️🤔 Частые вопросы

Что делать, если после включения заголовков сайт сломался?

Первым делом проверьте заголовок Content-Security-Policy, именно он вызывает подавляющее большинство поломок. Отключите CSP (или переключите в режим Report-Only) и проверьте сайт снова. Ошибка 500 после правки.htaccess, проверьте синтаксис: лишний пробел, незакрытые кавычки или отсутствие модуля mod_headers. Через FTP переименуйте.htaccess → сайт оживёт, и вы сможете спокойно найти ошибку.

В 9 из 10 случаев проблема именно в CSP, а не в остальных заголовках. X-Content-Type-Options, X-Frame-Options, HSTS и Referrer-Policy сломать сайт не могут физически, они не затрагивают рендеринг и логику PHP. Начинайте всегда с них.

Обязательно ли использовать плагин или можно через код?

Можно и нужно через код, если вы умеете править functions.php или.htaccess. Прямая установка заголовков через конфигурацию сервера работает быстрее плагина, нет прослойки PHP. Но плагин удобнее для тех, кто не хочет лезть в код, и даёт визуальный интерфейс с предустановками для каждого заголовка.

Мы на тестовых сайтах используем оба подхода: на продакшене,.htaccess (меньше точек отказа), на клиентских сайтах где хостинг не даёт править конфигурацию, плагин. Результат по securityheaders.com идентичен: A+ в обоих случаях.

Нужно ли настраивать CSP, если сайт на WordPress?

Для большинства сайтов, нет. CSP на WordPress требует unsafe-inline и unsafe-eval для работы Gutenberg и десятков плагинов — это снижает защитный эффект до символического. Полноценный CSP имеет смысл на высоконагруженных проектах с выделенным специалистом по безопасности, который будет разбирать каждый отчёт о нарушении. Для всех остальных 5 базовых заголовков дают львиную долю практической защиты.

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

Откройте сайт в браузере, запустите DevTools (F12) → вкладка Network → кликните на первый запрос к вашему домену → секция Response Headers. Если видите добавленные заголовки, всё работает. Для автоматической проверки используйте securityheaders.com, он показывает не только наличие, но и корректность значений, а также итоговую оценку от A+ до F.

Что делать, если хостинг не даёт править.htaccess и нет доступа к functions.php?

Установите Headers Security Advanced & HSTS WP через админку WordPress. Плагин внедряет заголовки на уровне PHP и не требует правки серверных файлов. Это работает на любом хостинге, где крутится WordPress, от дешёвого shared до Managed WordPress.

Влияют ли HTTP-заголовки на скорость сайта?

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

Что ставить и с чего начать

HTTP-заголовки безопасности, не разовая акция «поставил и забыл». Это baseline, который должен быть на каждом сайте по умолчанию, как SSL-сертификат.

План на сегодня:

  • Проверьте сайт на securityheaders.com. Если оценка D или F, у вас нет даже X-Content-Type-Options.

  • Добавьте 5 базовых заголовков любым из трёх способов выше. Если сайт на Apache, через.htaccess (30 секунд). Nginx без доступа к конфигу, через functions.php (2 минуты). Не хотите код, плагин Headers Security Advanced (3 минуты с установкой).

  • Перепроверьте сайт. Оценка должна подняться до A или A+.

  • CSP отложите. Вернитесь к нему, когда базовые заголовки отработают месяц без проблем, а у вас появится время на тестирование через Report-Only.

Один час, и у вашего WordPress-сайта появляется эшелон защиты, которого нет у подавляющего большинства сайтов в интернете. Начните с проверки прямо сейчас.