Правила безпеки .htaccess для WordPress, які справді допомагають
Більшість того, що продають як безпеку .htaccess для WordPress, — це вода. Правил, які реально змінюють вашу поверхню атаки, небагато — ось як відрізнити одні від інших
Опубліковано
Більшість того, що продають як «безпеку .htaccess для WordPress», — це вода. Правил, які реально змінюють вашу поверхню атаки, небагато: заблокувати виконання PHP усередині wp-content/uploads, заборонити прямий доступ до wp-config.php та вимкнути індексацію каталогів. Популярні поради — блокувати xmlrpc.php, «щоб зупинити брутфорс», приховувати версію WordPress, вставляти список із 200 рядків user-agent-ів «поганих ботів» — коливаються від сумнівних до чистого театру. Нижче — що є чим і чому.
Спершу з’ясуємо одну річ: .htaccess узагалі щось робить лише на Apache (і на LiteSpeed, який теж його читає). На nginx він повністю ігнорується — файл просто лежить собі, а ви вважаєте, що захищені. Якщо ваш хостинг працює на nginx, ніщо з цього не застосовується, і вам потрібні блоки server/location замість цього. Перевірте командою curl -I https://yoursite.com і подивіться на заголовок Server:, перш ніж витрачати годину на редагування файлу, який сервер ніколи не читає.
Правило, яке справді має значення: жодного PHP у /uploads
Ось те, що варто зробити. wp-content/uploads за задумом доступний для запису всім — кожне завантаження медіафайлу, кожен плагін, що зберігає файл, пишуть саме туди. Якщо зловмисник зможе покласти .php-файл у цей каталог (через вразливий обробник завантажень, поле зображення, яке не перевіряє MIME-тип, чи скомпрометований плагін), то різниця між дрібною прикрістю і повною компрометацією з віддаленим виконанням коду полягає лише в тому, чи виконає сервер цей файл на запит. Заборонивши виконання, ви перетворюєте завантажений payload на просто інертний файл, що лежить на диску.
Додайте це у wp-content/uploads/.htaccess (створіть файл, якщо його немає):
<FilesMatch "\.php$">
Require all denied
</FilesMatch>
Це синтаксис Apache 2.4. У старішій 2.2 еквівалентом буде Order Deny,Allow / Deny from all. Змішування двох діалектів в одному файлі — найпоширеніша причина раптового 500 Internal Server Error після «посилення захисту»: якщо весь сайт лягає в момент збереження, майже завжди причина саме в цьому. Перевірте свою версію командою apachectl -v.
Захистіть wp-config.php
wp-config.php містить дані доступу до бази даних і auth-солі. Поки PHP працює, прямий запит до нього повертає порожню сторінку — PHP виконує файл, а не виводить його. Ризик — у випадку збою: якщо PHP колись впаде, буде неправильно налаштований під час міграції чи обробник вимкнуть, Apache віддасть файл як звичайний текст і викине ваш пароль до БД будь-кому, хто попросить. Заборона доступу — це дешева страховка від однієї невдалої п’ятихвилинки:
<Files wp-config.php>
Require all denied
</Files>
Вимкніть індексацію каталогів
Якщо хтось заходить у теку без index.php, а в Apache увімкнено Options +Indexes, він виводить її вміст — кожен резервний файл, кожен забутий SQL-дамп. Вимкніть це для всього сайту:
Options -Indexes
Загроза невисока, але реальна, і це нічого не коштує.
Ось і весь чесний базовий перелік. Ви можете зібрати ці правила — разом із коректним синтаксисом 2.4 проти 2.2, щоб не покласти сайт із 500-кою — за допомогою генератора .htaccess для WordPress, а не копіювати з допису на форумі, написаного під іншу версію Apache.
Чого НЕ треба робити
Блокувати xmlrpc.php «для захисту від брутфорсу». Це головна порада, яку всі повторюють, і в такому формулюванні вона хибна. Так, метод system.multicall у XML-RPC історично дозволяв зловмиснику запакувати багато спроб входу в один запит — реальне посилення. Але переважна більшість брутфорс-атак — це звичайні POST-запити до wp-login.php, і блокування xmlrpc.php нічого з цим не робить. Брутфорс перемагають обмеженням частоти запитів, надійними паролями та 2FA — а не вбиванням одного endpoint-а. Є законна причина вимкнути XML-RPC: його функцію pingback можна зловживати для DDoS-рефлексії, тож якщо ви не використовуєте Jetpack, мобільний застосунок чи pingback-и, закриття його зменшує поверхню атаки. Тільки не переконуйте себе, що це ваш захист від брутфорсу, бо це не так.
Приховувати версію WordPress / прибирати тег генератора. Видалення readme.html і тега <meta name="generator"> створює відчуття посилення захисту. Зловмисник визначить вашу версію за query-рядками підключених ресурсів, розміткою блокового редактора та десятком інших ознак за лічені секунди. Ви нічого не приховуєте — ви лише створюєте собі ілюзію діяльності.
Величезні чорні списки user-agent-ів і реферерів «поганих ботів». User-agent — це один-єдиний HTTP-заголовок, який легко підробити. Ці списки застарівають того ж дня, коли ви їх вставили, вони не блокують нічого компетентного, а Apache обчислює кожен regex на кожен запит — ви платите реальний податок на продуктивність за нульову безпеку. Пропустіть їх.
Блокувати wp-login.php за IP. Чудово працює, поки ваш провайдер не змінить адресу і ви не заблокуєте самі себе від власної адмінки. Життєздатно лише зі справді статичним IP.
Редиректи проти перебору авторів (?author=1). Правило перезапису для .htaccess, яке для цього вставляють, саме по собі неповне — REST-endpoint /wp-json/wp/v2/users усе одно виводить імена користувачів. Блокувати один шлях, поки інший лишається відкритим, — це театр.
Досі не виходить?
Якщо правило кладе сайт із 500-кою — це синтаксис: приберіть останній доданий блок і перезавантажте; так ви одразу його ізолюєте. Якщо правило начебто нічого не робить, переконайтеся, що ви справді на Apache і що для каталогу увімкнено AllowOverride (багато керованих хостингів його обмежують). Зберіть файл із перевіреного шаблону за допомогою генератора .htaccess, лишіть три правила, які мають значення, а решту відкиньте.