После аудита у корпоративного сайта на WordPress оказалось: по адресу /wp-json/wp/v2/users отдаётся JSON со списком логинов всех авторов. Через неделю на wp-login.php пошёл перебор — бот уже знал, что пробовать. REST API сам по себе не «дыра», но публичный список пользователей и открытый XML-RPC превращают защиту пароля в лотерею. Ниже — что проверить за 10 минут и как закрыть утечку, не сломав редактор и WooCommerce.
Зачем WordPress REST API открыт по умолчанию
С версии 4.7 ядро WordPress REST API — штатный способ общения блок-редактора Gutenberg, мобильного приложения и части плагинов с сайтом. Эндпоинт /wp-json/ отвечает JSON: версия ядра, доступные маршруты, данные записей для публичного чтения.
Для обычного посетителя это невидимо. Для бота — карта сайта с подсказками: какие URL существуют, какие методы разрешены, кто пишет на сайте. Проблема не в том, что API есть, а в том, какие данные он отдаёт без авторизации.
Базовый чек-лист паролей, 2FA и лимита входа — в материале «Защита WordPress от взлома». Эта статья — про два вектора, которые там упоминаются вскользь: утечка логинов через REST и атаки через XML-RPC.
Утечка логинов: /wp-json/wp/v2/users

Откройте в браузере (или через curl):
https://ваш-сайт.ru/wp-json/wp/v2/users
Если видите массив объектов с полями slug, name, link — логины авторов и редакторов уже публичны. Поле slug в WordPress для пользователей — это и есть login name (nicename), который подставляется на форме входа.
Что это даёт атакующему:
- список целей для брутфорса вместо перебора
admin,administrator,editor; - связка «логин + архив автора» для социальной инженерии;
- подготовка к таргетированному фишингу «от имени техподдержки хостинга».
На многих свежих установках WordPress список пользователей для неавторизованных уже ограничен — но темы, старые плагины и кастомные сниппеты снова «открывают» эндпоинт. Проверять нужно на своём домене, а не по памяти.
Перебор авторов: ?author=1 и архивы

Даже если REST закрыли, остаётся классический приём:
https://ваш-сайт.ru/?author=1
https://ваш-сайт.ru/?author=2
WordPress часто делает 301 на /author/логин/. Перебор id от 1 до 10 занимает секунды. Архивы авторов на бизнес-сайте обычно не нужны — а логин на странице архива светится в URL.
Способы закрыть:
- редирект архивов авторов на главную через код в
functions.phpдочерней темы; - плагины вроде Stop User Enumeration или модуль в iThemes Security / Wordfence;
- блокировка
?author=в.htaccess(осторожно с кэширующими плагинами — тестировать после включения).
XML-RPC: перебор паролей пачками

Файл xmlrpc.php в корне — наследие удалённой публикации и Jetpack. Метод system.multicall позволяет отправить десятки попыток входа в одном запросе. Limit Login Attempts считает это за одну попытку с одного IP — брутфорс идёт быстрее.
Если не пользуетесь мобильным приложением WordPress, удалённой публикацией и Jetpack — XML-RPC лучше отключить полностью. Подробнее про способы — в разделе про XML-RPC в чек-листе защиты; отдельная проверка доступности — в инструменте «Проверка XML-RPC».
Минимальный блок в корневом .htaccess (Apache):
<Files xmlrpc.php>
Require all denied
</Files>
На Nginx — правило в конфиге через поддержку хостинга.
Как проверить сайт за 10 минут

Ручная проверка трёх URL выше — уже половина дела. Для системного отчёта с оценкой и списком видимых логинов используйте бесплатный инструмент «Открытость WP REST API» на saitporyadke.ru:
- запрос к
/wp-json/wp/v2/usersи разбор ответа; - перебор
?author=без агрессивного сканирования; - краткий обзор открытых REST-маршрутов;
- рекомендации, что закрыть в первую очередь.
Общий срез «версия, тема, следы плагинов» — в WP Quick Check; там же ссылка на углублённую проверку REST, если базовый аудит что-то подсветил.
Заголовки безопасности (HSTS, X-Frame-Options) — отдельно в инструменте заголовков. Это не закрывает утечку логинов, но дополняет картину.
Как закрыть утечку: от мягкого к жёсткому

1. Скрыть список пользователей (рекомендуется первым)
Код в functions.php дочерней темы или mu-plugin:
add_filter('rest_endpoints', function ($endpoints) {
if (isset($endpoints['/wp/v2/users'])) {
unset($endpoints['/wp/v2/users']);
}
if (isset($endpoints['/wp/v2/users/(?P<id>[\d]+)'])) {
unset($endpoints['/wp/v2/users/(?P<id>[\d]+)']);
}
return $endpoints;
});
Gutenberg и WooCommerce REST для заказов при этом обычно продолжают работать — мы убираем только публичный каталог пользователей.
2. Закрыть перебор author=
add_action('template_redirect', function () {
if (is_author() || isset($_GET['author'])) {
wp_safe_redirect(home_url(), 301);
exit;
}
});
После добавления — проверить, что нет нужных публичных страниц авторов (на корпоративных сайтах их почти никогда нет).
3. Плагины «на один клик»
Если править код неудобно:
- Disable REST API (или аналог с настройкой «только users») — читать описание: часть версий режет весь API и ломает редактор.
- Stop User Enumeration — узкая задача, мало конфликтов.
- Модули Wordfence / iThemes — опция «Block user enumeration» / REST hardening.
После любого плагина: зайти в админку, сохранить черновик в Gutenberg, оформить тестовый заказ в WooCommerce (если магазин).
4. .htaccess — только если понимаете откат
Пример блокировки только users (Apache 2.4):
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule ^wp-json/wp/v2/users - [F,L]
</IfModule>
Не блокируйте весь /wp-json/, если сайт на блоках или headless — перестанет работать редактор и часть интеграций.
Что НЕ делать
- Не отключать REST API целиком «ради безопасности» на сайте с Gutenberg — получите белый экран редактора и сбои WooCommerce Blocks.
- Не включать все галочки в плагине безопасности сразу. Типичная ошибка — описана в статье про защиту: ломается оплата, AJAX, REST для приложений.
- Не полагаться на «security through obscurity». Смена логина с
adminна редкое слово помогает, но не заменяет закрытие enumeration и сильный пароль + 2FA. - Не править .htaccess на боевом магазине в пятницу вечером без бэкапа и без staging. Ошибка в двух строках — ошибка 500 на весь домен.
- Не ставить два плагина, оба режущих REST. Лишний конфликт — см. разбор про лишние плагины.
Если логины уже «светились»
Закрытие эндпоинта не отменяет того, что логины могли сохраниться в кэше поисковиков или у атакующего. Минимум действий:
- Закрыть users + author enumeration (код или плагин выше).
- Сменить пароли всех пользователей с ролью от «Редактор» и выше — длинные, уникальные.
- Включить 2FA для админов (если ещё нет).
- Limit Login Attempts + при необходимости WPS Hide Login.
- Проверить журнал входа / Wordfence — не было ли успешных входов с незнакомых IP.
Если находите следы взлома — пошаговый план в «Сайт взломали — что делать». Перед правками — рабочий бэкап, не «галочка в плагине, который сам не обновлялся год».
Чек-лист на сегодня

- Открыть
/wp-json/wp/v2/usersили прогнать проверку REST API. - Проверить
/?author=1— есть ли редирект с логином в URL. - Убедиться, что
xmlrpc.phpне нужен — иначе отключить. - Убрать пользователя
admin, включить 2FA и лимит входа. - Закрыть users через код или плагин, не резать весь REST.
- Через неделю повторить проверку и убедиться, что кэш/CDN не отдаёт старый JSON.
Когда звать специалиста
Настройка на типовом корпоративном сайте — 30–60 минут, если есть FTP и доступ к теме. Имеет смысл передать задачу, если:
- headless- или multisite-конфигурация — REST используется приложением;
- после правок падает checkout или редактор — нужна разбор конфликта плагинов;
- сайт уже атаковали, нужен аудит «что ещё открыто».
Настройка под ключ — услуга «Безопасность WordPress» или сообщение через Контакты. Для самостоятельной проверки начните с проверки открытости REST API — результат можно сохранить и сравнить «до/после» правок.



