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 что-то нашёл, права на эти файлы шире, чем задано в первом разделе статьи, и их нужно поправить отдельно.