WordPress — найбільш атакована CMS у світі. Близько 90% зламів пов'язані із застарілими плагінами, слабкими паролями та відкритим xmlrpc.php. Цей чеклист закриває всі основні вектори атак.
1. Права на файли та директорії
find /var/www/wordpress -type d -exec chmod 755 {} \;
find /var/www/wordpress -type f -exec chmod 644 {} \;
chmod 400 /var/www/wordpress/wp-config.php
chown www-data:www-data /var/www/wordpress/wp-config.php
2. Захист wp-config.php та uploads у Nginx
location = /wp-config.php { deny all; }
location ~* /wp-content/uploads/.*\.php$ { deny all; }
3. Вимкнути xmlrpc.php
location = /xmlrpc.php { deny all; access_log off; log_not_found off; }
4. Захист сторінки входу
location = /wp-login.php {
allow 1.2.3.4;
deny all;
fastcgi_pass unix:/var/run/php/php8.3-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
5. Доповнення у wp-config.php
define('DISALLOW_FILE_EDIT', true);
define('DISALLOW_FILE_MODS', true);
// Згенерувати ключі: https://api.wordpress.org/secret-key/1.1/salt/
define('AUTH_KEY', 'унікальний_ключ_1');
define('SECURE_AUTH_KEY', 'унікальний_ключ_2');
6. Чеклист WordPress Security
| Захід | Інструмент | Пріоритет |
|---|---|---|
| Оновити WP, теми, плагіни | Авто-оновлення | Критичний |
| Сильний пароль + 2FA | WP 2FA плагін | Критичний |
| Вимкнути xmlrpc.php | Nginx | Високий |
| Права 644/755 на файли | chmod | Високий |
| WAF / Firewall | Wordfence, Sucuri | Високий |
| Приховати wp-login.php URL | WPS Hide Login | Середній |
| Резервні копії | UpdraftPlus | Критичний |
| SSL-сертифікат | Let's Encrypt | Критичний |
Плагіни — головна загроза: 56% зламів WordPress відбувається через вразливі плагіни. Регулярно оновлюйте всі плагіни та видаляйте невикористовувані — навіть деактивовані плагіни залишаються вразливістю.
Розбір типових помилок під час захисту WordPress
- Запит
GET /xmlrpc.phpу браузері повертає текстXML-RPC server accepts POST requests only.— ендпоінт живий і відповідає, просто чекає POST-запит. Сам факт відповіді200 OKозначає, що правилоdeny allще не застосувалося. - Конфіг Nginx відредаговано, а
/wp-login.phpз чужої мережі й досі відкривається — типова причина: правки внесли не в тойserver {}, якщо на сервері окремі блоки для HTTP і HTTPS чи для кількох доменів, а виправили лише один із них. access forbidden by rule, client: ..., server: ..., request: "GET /wp-config.php HTTP/1.1"— так виглядає в журналі Nginx успішне блокування черезdeny all; у браузері при цьому видно звичайний403 Forbidden.- Резервна копія редактора на кшталт
wp-config.php~чиwp-config.php.bakвіддається сервером як звичайний текст, а не виконується як PHP — правилоlocation = /wp-config.phpзбігається лише з точною назвою файлу, а копія з іншим розширенням проходить повз нього і розкриває пароль від бази даних відкритим текстом. - Атака на
xmlrpc.phpметодомsystem.multicallперевіряє тисячі паролів одним HTTP-запитом замість тисяч окремих спроб — тому вимкнення xmlrpc.php знижує ризик сильніше, ніж здається по одному на вигляд нешкідливому ендпоінту.
Способи захисту wp-login.php: що дають і де слабке місце
| Спосіб | Що дає | Слабке місце |
|---|---|---|
| IP allowlist в Nginx | Повністю закриває вхід стороннім адресам | Ламається при динамічному IP, потребує регулярного оновлення правила |
| HTTP Basic Auth перед формою входу | Додатковий пароль ще до форми WordPress | Один спільний пароль на всіх, не привʼязаний до конкретного користувача |
| Приховування URL (WPS Hide Login) | Зупиняє автоматичний перебір ботами за стандартною адресою | Не захищає від цільової атаки, якщо адреса все ж стала відомою |
| Двофакторна автентифікація | Захищає акаунт навіть у разі витоку пароля | Не обмежує кількість спроб входу в саму форму |
Коли ці заходи не підходять як є
- WordPress Multisite з різними шляхами для кожного сайту мережі — жорсткі правила
location =на конкретний шлях можуть не збігтися з реальними URL мережі, схему потрібно адаптувати під конкретну інсталяцію. - Керований хостинг без доступу до конфігурації Nginx, лише .htaccess чи панель керування — правила з блоку
server {}застосувати не можна, працює лише те, що підтримує панель чи Apache через .htaccess. - Команда регулярно править теми й плагіни через вбудований файловий редактор в адмінці — увімкнення
DISALLOW_FILE_EDITзламає звичний процес; потрібен перехід на SFTP чи git-деплой або відмова від цього конкретного заходу. - Сайт віддає дані мобільному застосунку чи headless-фронтенду через REST API — поради щодо блокування
xmlrpc.phpне поширюються на REST API (/wp-json/), це окремий механізм із власними правилами доступу.
Перевірка, що захист реально працює
# Переконатися, що xmlrpc.php справді закрито (очікується 403, а не 200)
curl -I https://example.com/xmlrpc.php
# Перевірити, що резервні копії редактора не віддаються як текст
curl -I https://example.com/wp-config.php~
curl -I https://example.com/wp-config.php.bak
# Знайти на сервері файли, доступні на запис усім поспіль
find /var/www/wordpress -type f -perm /o+w
Перші три запити мають повернути 403 чи 404, а не 200. Остання команда має повернути порожній список: якщо find щось знайшов, права на ці файли ширші, ніж задано в першому розділі статті, і їх потрібно виправити окремо.