
🔒 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 і так далі.
Формат: название-фичи=(разрешённый-источник). Наприклад:
1 Permissions-Policy: camera=(), microphone=(), geolocation=(self)
Цей приклад повністю забороняє доступ до камери та мікрофона для всіх джерел, а геолокацію дозволяє тільки для самого сайту (self).
Повний список фіч, на MDN. Для WordPress-сайту без відеочатів і PWA-функцій достатньо закрити камеру, мікрофон і геолокацію, решта опціонально.
Рекомендоване значення: залежить від функціоналу сайту. Мінімум, camera=(), microphone=(), geolocation=(self).
Ризики поломок: якщо на сайті є функціонал відеодзвінків, PWA або WebUSB, перевірте, які фічі йому потрібні, і не закривайте їх.
Content-Security-Policy (CSP)
Найпотужніший і найнебезпечніший у налаштуванні заголовок. Визначає білий список джерел для скриптів, стилів, шрифтів, зображень, фреймів та інших ресурсів.
Приклад мінімальної політики для WordPress:
1 Content-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:
1 function 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 } 8 add_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-сайту з'являється ешелон захисту, якого немає у переважної більшості сайтів в інтернеті. Почніть із перевірки прямо зараз.


