Как отключить XML-RPC в WordPress: 3 способа & как распознать атаки на xmlrpc.php | исключение для Jetpack

Уведомление о партнёрских ссылках v3.1
Уведомление о партнёрских ссылках v3.2 (мобильная версия)

Если в журнале доступа сайта WordPress с одного IP подряд идут сотни запросов к xmlrpc.php, это подбор паролей через XML-RPC WordPress. На сервере Nginx + Apache с несколькими сайтами WordPress разобраны 8 624 записи журнала доступа за один день, три способа отключения применены на практике и проверены по кодам ответа — и по итогам показано, на каком уровне нужно блокировать, чтобы сократились даже запуски PHP.

XML-RPC — протокол, по которому функции WordPress вызываются удалённо через обмен XML-документами по HTTP. Начиная с WordPress 3.5 переключателя для него на экране настроек нет, поэтому сразу после установки он работает включённым.

1️⃣ Что делает xmlrpc.php и кто его использует

С появлением REST API легко решить, что [xmlrpc.php] — файл, которым больше никто не пользуется, но Jetpack до сих пор связывает через него сайт с WordPress.com. В официальной документации Jetpack прямо сказано, что он зависит от соединения XML-RPC, и на хостингах, где XML-RPC заблокирован по умолчанию, не удаётся даже само подключение Jetpack. Это как в наши дни всё ещё держать в офисе один номер факса.

По состоянию на WordPress 7.1 этот файл принимает 77 методов: 50 из семейства wp, которые работают с записями, медиафайлами и комментариями, 23 из старых протоколов блогов (MetaWeblog, MovableType, Blogger), 2 для пингбэков и 2 тестовых метода demo.

Методы семейства wp выполняют вход по имени пользователя и паролю из тела запроса, поэтому страницу входа они обходят. Создание и редактирование записей, загрузка медиафайлов, управление комментариями — всё это методы этого семейства, а 23 метода старых протоколов блогов оставлены для обмена записями тем же способом, что и в других инструментах для блогов.

demo.sayHello — тестовый вызов, встроенный в XML-RPC WordPress. В ответ он возвращает всего одно слово — [Hello!], а поскольку вход для него не нужен, его используют, чтобы проверить, работает ли XML-RPC. В пару к нему есть demo.addTwoNumbers, который складывает два числа и возвращает сумму.

Все они отвечают, только если отправить тело XML методом POST; если открыть адрес в браузере, вернётся 405 с сообщением [XML-RPC server accepts POST requests only.].

Пингбэки — тоже задача этого файла. При публикации записи пингбэк отправляется на xmlrpc.php сайтов, на которые есть ссылки в тексте, а принимающий сервер сам открывает адрес отправителя и проверяет, действительно ли там есть ссылка.

🧭 Запросы к xmlrpc.php и их обработка
Защита wp-adminПоясняющая схема
📨 Отправитель
↓
Точка входа
xmlrpc.php
Обрабатывает только тело XML, отправленное методом POST
405 · XML-RPC server accepts POST requests only.
77 методов
wp.*записи · медиафайлы · комментарии — 50
metaWeblog · mt · bloggerстарые протоколы блогов — 23
pingback.*пингбэки — 2
demo.*тестовые вызовы для проверки работы — 2
Результат
Поддерживает соединение с WordPress.com
Проверка имени пользователя и пароля из тела запроса → создание и правка записей
Сервер сам открывает адрес отправителя и проверяет ссылку
Без входа: Hello! Ответ
Не обрабатывается
Jetpack поддерживает соединение с WordPress.com через этот файл, поэтому если закрыть файл, соединение прервётся.
Внешние инструменты публикации входят по имени пользователя и паролю из тела запроса, минуя страницу входа.
Пингбэк отправляется на xmlrpc.php сайта, на который ссылается запись, а принимающий сервер сам открывает адрес отправителя и проверяет ссылку.
demo.sayHello — тестовый вызов для проверки того, работает ли XML-RPC; без входа он отвечает одним словом [Hello!].
Если открыть адрес в браузере, вернётся 405 с сообщением [XML-RPC server accepts POST requests only.].

2️⃣ Атаки на xmlrpc.php в журнале доступа

Подбор паролей идёт не через страницу входа, а через [xmlrpc.php]. В журнале доступа сервера Nginx + Apache с несколькими сайтами WordPress за 14 октября с 0:00 до 20:00 было 8 624 запроса POST /xmlrpc.php с 72 IP-адресов, и 19 из этих IP отправили ровно по 300 запросов.

Один IP отправил 300 запросов за 28 минут, с 14:09 до 14:37, и интервал в 5–6 секунд оставался ровным до самого конца. 8 524 запроса пришли с Jetpack или WordPress.com в User-Agent, причём один и тот же IP чередовал несколько значений, подражающих настоящему формату Jetpack, например [Jetpack by WordPress.com (Jetpack 13.0; WordPress 6.3)].

В тот же день до 14:00 отключение XML-RPC в плагине безопасности отправляло эти запросы на главную с кодом 302, а после 14:00, когда их заблокировали в Nginx, они завершались кодом 403. 302 означает, что PHP запускался на каждый запрос, даже если тело ответа было 0 байт, а 403 — ответ, который до PHP не дошёл.

🧭 Атака на xmlrpc.php в одной строке журнала доступа
Поясняющая схема
🛡️ Состояние сервера
Одна строка журнала доступа (Nginx access.log)
203.0.113.25IP[14/Oct/2026:14:09:04 +0900]Время"POST /xmlrpc.php HTTP/1.1"Запрос302403Статус0153Байты"Jetpack by WordPress.com (Jetpack 13.0; WordPress 6.3)"User-Agent
PHP запускается · 302 на главнуюБез PHP · стандартная страница 403 Nginx
Когда XML-RPC отключён плагином безопасности, в журнал записывается 302, который отправляет запрос на главную. Тело ответа — 0 байт, но чтобы выдать этот 302, запускается PHP.
При блокировке в Nginx в журнал записываются 403 и 153 байта стандартной страницы ошибки, а PHP не запускается.
Запросы с одного IP
14:09:0414:37:20
300 за 28 минут, интервал 5–6 с
POST с 0:00 до 20:00: 8 62472 IP19 IP, отправивших по 3008 524 с поддельным UA Jetpack·WordPress.com

3️⃣ system.multicall и подбор паролей

Часто пишут, что через [system.multicall] за один запрос перебирают сотни паролей, но если внутри одного запроса вход один раз не удался, WordPress уже не сверяет пароли в остальных вызовах. Через wp_authenticate проходит только первый вызов, а последующие без проверки получают ту же ошибку [Incorrect username or password.].

При этом ответ возвращается на каждый вызов, поэтому на один запрос со 100 неверными паролями за 0,12 секунды приходит ответ размером 23 КБ со 100 ошибками. Если в том же запросе правильный пароль стоит позже, он отклоняется вместе с остальными из-за неудачи предыдущего вызова, а если первым — успешен только этот вызов. Пароль сверяется один раз, но разбор XML и загрузка WordPress повторяются на каждый запрос, так что нагрузку на сервер при этой атаке создаёт само число запросов, а не проверка входа.

4️⃣ 3 способа отключить XML-RPC и коды ответа

Даже если отключить XML-RPC в плагине, запросы к [xmlrpc.php] доходят до PHP. При отключении фильтром на запрос со 100 вызовами всё равно пришли HTTP 200 и 100 ошибок (24 КБ). В зависимости от того, на каком уровне запрос отклоняется, способов три, и коды ответа у них разные.

1. Отключение в коде: фильтр xmlrpc_enabled

Достаточно добавить в functions.php темы одну строку add_filter, которая возвращает false для фильтра [xmlrpc_enabled]. В этом состоянии вызовы, требующие входа, отклоняются с ошибкой [XML-RPC services are disabled on this site.] и HTTP 405, но тестовый вызов demo.sayHello, которому вход не нужен, по-прежнему отвечает 200.

2. Отключение в настройках плагина: Perfmatters·Hide My WP

Это способ отключения через настройку Disable XML-RPC в таких плагинах, как Perfmatters и Hide My WP. Hide My WP использует тот же фильтр, что и выше, поэтому и ответы у него те же, а Perfmatters вдобавок к фильтру завершает прямые запросы к [xmlrpc.php] кодом 403 и удаляет заголовок и ссылку пингбэка, так что после отключения и GET, и POST получают 403. Однако чтобы выдать этот 403, WordPress выполняется вплоть до этапа init, поэтому ответ занимает те же 0,13–0,15 секунды, что и при открытом XML-RPC, и нагрузка на PHP остаётся.

🔌 Отключение XML-RPC в настройках плагина
📍 Settings › Perfmatters › General › Core › Disable XML-RPC
Включите переключатель и нажмите [Save Changes] — экран посетителя ниже изменится.
Админка
Settings saved.
perfmatters
⚙ GeneralVersion 2.6.8
Core
Disable Emojis?
Disable Dashicons?
Disable Embeds?
Disable XML-RPC?
Remove RSD Link?
Remove jQuery Migrate?
Hide WP Version?
Remove Shortlink?
Disable RSS Feeds?
Remove RSS Feed Links?
Disable Self Pingbacks?
Disable REST API?
Remove REST API Links?
Disable Google Maps?
Disable Password Meter?
Disable Comments?
Remove Comment URLs?
Add Blank Favicon?
Remove Global Styles?
Block Style Behavior?
Disable Heartbeat?
Heartbeat Frequency?
Limit Post Revisions?
Autosave Interval?
Login URL
Custom Login URL?
Disabled Behavior?
Message?
📍 Hide My WP › Settings › Cleanup › Disable XML RPC
Поставьте галочку и нажмите [Save Settings] — экран посетителя ниже изменится.
Админка
Hide My WP
Settings was updated successfully!
Cleanup
Minify HTML
Remove comments and whitespaces from HTML (Use with cache).
Minify style
Remove theme info and other comments from stylesheet. (Require new style name)(Use with cache!).
Replace \/ URLs
Choose if you see Javascript URLs (e.g. \/wp-content\/themes)
Feed Meta
Other Meta
Default Tagline
Remove Version
Body Classes
Menu Classes
Post Classes
Clean up other
Replace in AJAX
Change Nonce
Disable XML RPC
Internal CSS
Useful to paste internal CSS code (Require New Theme Path)
Internal JS
Useful to paste internal JS code (Require New Theme Path)
Экран посетителя без входа — запрос с сохранёнными настройками
405
XML-RPC server accepts POST requests only.
GET-запрос при любых настройках получает 405.
200
Hello!
Это тестовый вызов для проверки работы, поэтому он отвечает без входа.
200
faultCode 403 · Incorrect username or password.
Пароль сверяется. Смена адреса входа этого не меняет.
403
Пустое тело ответа
Perfmatters завершает запрос кодом 403 на этапе init. PHP при этом запускается.
403
Пустое тело ответа
Perfmatters завершает запрос кодом 403 на этапе init. PHP при этом запускается.
403
Пустое тело ответа
Завершается кодом 403 без сверки пароля. PHP при этом запускается.
200
Hello!
Это фильтр, поэтому вызовы, которым вход не нужен, отвечают как обычно.
405
faultCode 405 · XML-RPC services are disabled on this site.
Отклоняются только вызовы, требующие входа.

3. Блокировка на веб-сервере: Nginx·Apache

И Nginx, и Apache отклоняют запрос ещё до PHP, поэтому, в отличие от способов с плагином, WordPress не запускается.

# Nginx — внутри блока server, выше location для PHP
location = /xmlrpc.php {
    deny all;
}

Этот блок location ставится выше location, который обрабатывает PHP, и Nginx сразу отклоняет запросы, точно совпадающие с [xmlrpc.php]. После добавления проверьте конфигурацию и перезагрузите её — только тогда изменения вступят в силу.

nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
systemctl reload nginx

После перезагрузки GET и POST завершаются кодом 403, не доходя до PHP; тело ответа — стандартная страница 403 Nginx размером 153 байта, а ответ приходит за 0,02 секунды.

# Apache — .htaccess в корне сайта (Apache 2.4)
<Files xmlrpc.php>
    Require all denied
</Files>

На сервере только с Apache достаточно добавить приведённую выше директиву Files в .htaccess в корне сайта — она применяется сразу, и стандартная страница 403 Apache (199 байт) возвращается за те же 0,02 секунды.

curl -s -o /dev/null -w '%{http_code}' -X POST https://example.com/xmlrpc.php -d '<methodCall><methodName>demo.sayHello</methodName></methodCall>'
403

Команда выше отправляет тестовый вызов demo.sayHello методом POST и проверяет код ответа; после блокировки на веб-сервере возвращается 403. Если убрать опции [-o /dev/null] и [-w], будет видно тело ответа: [Hello!] означает, что XML-RPC открыт, но сайт, где он отключён только фильтром, отвечает так же, поэтому, чтобы увидеть 405, нужно отправить ещё и вызов со входом.

5️⃣ Когда отключать нельзя и что делать вместо этого

Полная блокировка на веб-сервере даёт наибольший эффект, но не подходит сайтам, подключённым к WordPress.com через Jetpack. Jetpack зависит от соединения XML-RPC, и на хостингах, где XML-RPC заблокирован по умолчанию, как у WP Engine, подключиться можно, только открыв исключение по инструкции Jetpack. То же касается сайтов, которые хотят принимать пингбэки.

Такие сайты сужают доступ: разрешают только список IP, который публикует Jetpack (jetpack.com/ips-v4.txt), а остальные запросы отклоняют. Достаточно добавить в блок location Nginx по строке allow на каждый диапазон IP и в конце поставить deny all.

Если полностью закрыть XML-RPC нельзя, остаётся ограничить число запросов без входа в минуту. Настройка та же, что в разделе об ограничении частоты в Nginx статьи Защита wp-admin — учитываются только запросы без cookie входа, поэтому на работу вошедшего администратора это не влияет.

🔢 FAQ & рекомендуемые материалы

Даже если его удалить, при обновлении ядра WordPress файл из пакета будет скопирован заново, так что при следующем обновлении он вернётся. В отличие от удаления, блокировка этого адреса на веб-сервере или отключение фильтром сохраняются и после обновлений.

REST API — отдельный вход по адресу [wp-json], поэтому после отключения XML-RPC он остаётся открытым. Этот вход использует редактор блоков, так что правильнее не отключать REST API полностью, а блокировать только запросы без входа.

Никак — они не проверяют, а просто отправляют запросы. У любого сайта на WordPress этот файл лежит по одному и тому же пути, поэтому сканеры лишь меняют адрес и шлют POST-запросы. К тому же WordPress в состоянии по умолчанию сам раскрывает адрес xmlrpc.php — ссылкой [EditURI] в head страницы и заголовком [X-Pingback] у записей, принимающих пингбэки.

🛡️ Рекомендуемые материалы по безопасности WordPress 8 статей · 2 внешние
🗂️ Безопасность WordPress
📋 Защита wp-admin 📄 Атаки перебором: 9 способов 📄 Hide My WP 📄 Плагины безопасности: Best 5
📄 Отключение XML-RPC 📄 REST API 📄 Пингбэки · трекбэки 📄 Защита wp-config.php
📡 Nanaco Japan: защита от атак на xmlrpc.php 📡 サイトの主治医: отключение и проверка xmlrpc.php
Ничего не найдено.
Защита wp-admin: входы в WordPress
Безопасность · wp-admin
Безопасность WP: защита wp-admin | смена адреса входа, ограничение входа, XML-RPC
Смена адреса входа и ограничение попыток входа, закрытие xmlrpc.php и ограничение частоты в Nginx: порядок блокировки автоматических запросов ко входу в админку с проверкой по журналу доступа.
Читать →Текущая статья
Атака перебором (brute-force attack)
Безопасность · Вход
9 способов остановить атаки перебором (brute-force attack) на WordPress
Девять способов остановить попытки входа на сайте, где адрес wp-admin виден всем.
Читать →Текущая статья
Симулятор настроек Hide My WP
Безопасность · Hide My WP
Hide My WP: дополнительный плагин безопасности WordPress | скрытие wp-admin & адреса входа и ещё около 40 функций
Скрытие адреса входа и wp-admin, смена путей тем и плагинов, обнаружение вторжений и блокировка IP, отключение XML-RPC — около 40 функций перенесены в симулятор настроек.
Читать →Текущая статья
Сравнительная таблица плагинов безопасности WordPress
Безопасность · плагины
Плагины безопасности WordPress: сравнение Best 5
Сравнение пяти плагинов безопасности WordPress по защите от перебора паролей, проверке на вредоносный код и брандмауэру.
Читать →Текущая статья
XML-RPC в WordPress: как распознать атаки на xmlrpc.php
Безопасность · XML-RPC
XML-RPC в WordPress: как распознать атаки на xmlrpc.php и отключить XML-RPC | исключение для Jetpack
Атаки распознаются по запросам к xmlrpc.php в журнале доступа, а три уровня отключения — фильтр, плагин и веб-сервер — сравниваются по реально измеренным кодам ответа. Разобрано и исключение для сайтов с Jetpack.
Читать →Текущая статья
Симулятор настроек WordPress REST API
Безопасность · REST API
WordPress REST API: почему не отключать полностью, а закрывать только для неавторизованных
Проблема: посетителям без входа через адрес wp-json раскрываются имена пользователей. Решение — не отключать REST API полностью, а блокировать только запросы без входа и проверять результат по ответу 401.
Читать →Текущая статья
Пингбэки и трекбэки WordPress
Безопасность · пингбэки
Что такое пингбэки и трекбэки в WordPress? 2 способа их отключить
Плюсы и минусы пингбэков и трекбэков и два способа их отключить.
Читать →Текущая статья
Файл wp-config.php в WordPress
Безопасность · wp-config.php
Уязвимости wp-config.php: усиление защиты WordPress
Проверка защиты wp-config.php по шести пунктам — вместе со случаем swap-копии, которая открывалась по веб-адресу.
Читать →Текущая статья

ℹ️ О партнёрских ссылках
Материалы этого сайта содержат партнёрские ссылки. Если посетитель покупает товар или услугу по такой ссылке, сайт получает комиссию от продавца. При этом сумма, которую платит покупатель (при акционных скидках сумма снижается ↓), не увеличивается. Указанные цены, скидки и наличие актуальны на момент написания и могут отличаться, поэтому перед покупкой уточняйте их у продавца. Товары выбираются и оцениваются по нашим собственным критериям, а комиссия не влияет ни на порядок, ни на содержание обзоров.