XML-RPC es un protocolo de llamada a procedimiento remoto que WordPress soporta desde sus inicios. El archivo xmlrpc.php se encuentra en el directorio raíz de WordPress y proporciona una API para que aplicaciones externas se comuniquen con tu sitio. Si bien esto era genuinamente útil allá por 2008 cuando no había mejores alternativas, la REST API (introducida en WordPress 4.7, diciembre de 2016) la ha sustituido por completo para los usos legítimos. Hoy, XML-RPC es explotado principalmente por atacantes para intentos de inicio de sesión por fuerza bruta y ataques de amplificación DDoS. Si no usas Jetpack ni una herramienta heredada de publicación móvil, deberías deshabilitarlo.
La historia de XML-RPC en WordPress
El soporte de XML-RPC ha formado parte de WordPress desde la versión 1.5 (2005), pero estaba deshabilitado por defecto. Los propietarios de sitios tenían que habilitarlo manualmente en Ajustes si querían usar clientes de blogging de escritorio como Windows Live Writer o MarsEdit. En WordPress 3.5 (diciembre de 2012), la interfaz XML-RPC se habilitó por defecto y se eliminó la opción de deshabilitarla a través de la interfaz de administración. La razón era que las aplicaciones móviles y los servicios externos dependían cada vez más de ella. Sin embargo, esta decisión también significó que cada instalación de WordPress tenía ahora un endpoint de API abierto que los atacantes podían atacar.
Con WordPress 4.7 (diciembre de 2016), la REST API pasó a formar parte del núcleo de WordPress. La REST API ofrece una interfaz moderna basada en JSON que es más flexible, está mejor documentada y es más fácil de proteger que XML-RPC. La aplicación móvil de WordPress cambió de XML-RPC a la REST API en 2019. En este punto, el único servicio importante que aún requería XML-RPC era Jetpack, e incluso Jetpack ha ido reduciendo su dependencia de XML-RPC con el tiempo.
Cómo funciona el ataque de fuerza bruta system.multicall
El aspecto más peligroso de XML-RPC es el método system.multicall. Los ataques de fuerza bruta normales contra la página de inicio de sesión de WordPress prueban una combinación usuario/contraseña por petición HTTP. La limitación de tasa y plugins como Limit Login Attempts pueden bloquear estos ataques eficazmente porque cada intento genera una petición separada.
El método system.multicall de XML-RPC cambia la ecuación por completo. Un atacante puede agrupar cientos o incluso miles de intentos de autenticación wp.getUsersBlogs en una sola petición HTTP. Desde la perspectiva del servidor, esto parece una sola petición. Desde la perspectiva del atacante, acaban de probar 500 contraseñas. Los plugins de limitación de tasa de inicio de sesión que funcionan a nivel de aplicación a menudo no detectan estos intentos porque solo ven una petición entrante.
Así es como se ve un payload de fuerza bruta multicall:
<?xml version="1.0"?>
<methodCall>
<methodName>system.multicall</methodName>
<params>
<param>
<value><array><data>
<value><struct>
<member>
<name>methodName</name>
<value><string>wp.getUsersBlogs</string></value>
</member>
<member>
<name>params</name>
<value><array><data>
<value><string>admin</string></value>
<value><string>password123</string></value>
</data></array></value>
</member>
</struct></value>
<!-- siguen cientos de intentos más -->
</data></array></value>
</param>
</params>
</methodCall>Amplificación DDoS mediante pingbacks
El segundo gran vector de ataque es la funcionalidad de pingback de XML-RPC. Los pingbacks son notificaciones enviadas entre sitios WordPress cuando un sitio enlaza con otro. Los atacantes abusan de esto enviando peticiones de pingback falsificadas a miles de sitios WordPress, todas apuntando a una única URL objetivo. Cada sitio WordPress envía entonces una petición de verificación al objetivo, convirtiendo de hecho miles de instalaciones de WordPress en una botnet de denegación de servicio distribuido (DDoS). El servidor objetivo se ve abrumado por peticiones entrantes desde sitios WordPress legítimos, lo que dificulta su bloqueo.
Cómo comprobar si XML-RPC está habilitado actualmente
Antes de hacer cambios, comprueba si XML-RPC está activo en tu sitio. Puedes usar curl desde la línea de comandos:
curl -X POST https://tusitio.com/xmlrpc.php
-H "Content-Type: text/xml"
-d '<?xml version="1.0"?><methodCall><methodName>system.listMethods</methodName></methodCall>'Si XML-RPC está habilitado, recibirás una respuesta XML que lista todos los métodos disponibles (normalmente más de 80). Si está deshabilitado o bloqueado, obtendrás un error 403 Forbidden, un error de conexión rechazada o un mensaje "XML-RPC server accepts POST requests only" (dependiendo de cómo se haya deshabilitado).
Comprobar los logs del servidor en busca de ataques XML-RPC
Antes de deshabilitar XML-RPC, conviene revisar tus logs de acceso para ver si ya estás siendo objetivo. Busca peticiones POST a xmlrpc.php:
# Log de acceso de Apache
grep "xmlrpc.php" /var/log/apache2/access.log | tail -50
# Log de acceso de Nginx
grep "xmlrpc.php" /var/log/nginx/access.log | tail -50
# Contar peticiones por IP
grep "xmlrpc.php" /var/log/apache2/access.log | awk '{print $1}' | sort | uniq -c | sort -rn | head -20Si ves cientos o miles de peticiones POST a xmlrpc.php desde varias direcciones IP, tu sitio está siendo activamente atacado. Esto es muy común y es una razón más para deshabilitar el endpoint por completo.
Método 1: Bloquear a nivel del servidor web (recomendado)
Bloquear XML-RPC a nivel del servidor web es el enfoque más eficaz porque la petición se rechaza antes incluso de que se cargue PHP. Esto ahorra recursos del servidor y es el enfoque que deberías preferir frente al filtrado a nivel de PHP.
Apache (.htaccess)
Añade esto a tu archivo .htaccess en el directorio raíz de WordPress:
# Bloquear todo acceso a xmlrpc.php
<Files xmlrpc.php>
Order deny,allow
Deny from all
</Files>Si necesitas permitir direcciones IP específicas (por ejemplo, si usas Jetpack), puedes añadir excepciones:
<Files xmlrpc.php>
Order deny,allow
Deny from all
Allow from 122.248.245.244
Allow from 54.217.201.243
</Files>Nginx
Añade esto dentro de tu bloque server en la configuración de Nginx:
location = /xmlrpc.php {
deny all;
access_log off;
log_not_found off;
return 403;
}Las directivas access_log off y log_not_found off evitan que tus archivos de log se llenen con intentos bloqueados de XML-RPC, que pueden alcanzar gigabytes en sitios muy atacados.
Método 2: Deshabilitar mediante un filtro de WordPress (a nivel de PHP)
Si no puedes modificar los archivos de configuración del servidor (común en hosting compartido), puedes deshabilitar XML-RPC a nivel de PHP. Añade esto al functions.php de tu tema o, mejor aún, a un must-use plugin personalizado:
// Deshabilitar XML-RPC por completo
add_filter('xmlrpc_enabled', '__return_false');
// Eliminar el enlace de descubrimiento XML-RPC del head HTML
remove_action('wp_head', 'rsd_link');
// Eliminar la cabecera HTTP X-Pingback
add_filter('wp_headers', function($headers) {
unset($headers['X-Pingback']);
return $headers;
});Importante: el filtro xmlrpc_enabled solo deshabilita los métodos XML-RPC basados en autenticación. El archivo xmlrpc.php sigue cargándose, PHP sigue ejecutándose y los métodos sin autenticar (como los pingbacks) pueden seguir funcionando. Por eso se prefiere bloquear a nivel del servidor. El enfoque del filtro sigue consumiendo recursos del servidor procesando la petición antes de rechazarla finalmente.
Crear un must-use plugin (recomendado frente a functions.php)
En lugar de añadir código a functions.php (que se sobrescribe durante las actualizaciones del tema), crea un must-use plugin. Crea el archivo wp-content/mu-plugins/disable-xmlrpc.php:
<?php
/**
* Plugin Name: Disable XML-RPC
* Description: Deshabilita por completo la funcionalidad XML-RPC
*/
add_filter('xmlrpc_enabled', '__return_false');
remove_action('wp_head', 'rsd_link');
add_filter('wp_headers', function($headers) {
unset($headers['X-Pingback']);
return $headers;
});Los must-use plugins se cargan antes que los plugins normales y no pueden desactivarse accidentalmente desde la interfaz de administración.
Método 3: Configuración de un plugin de seguridad
Si utilizas un plugin de seguridad como Wordfence, Sucuri o iThemes Security, ofrecen opciones integradas para deshabilitar XML-RPC:
- Wordfence: Ve a Wordfence > All Options > Brute Force Protection. El firewall limita automáticamente la tasa de intentos de autenticación XML-RPC. Para un bloqueo completo, usa el método a nivel de servidor descrito arriba.
- iThemes Security: Ve a Security > Settings > WordPress Tweaks. Activa "Disable XML-RPC" para bloquearlo por completo, o selecciona "Disable Pingbacks" para bloquear solo el vector de abuso de pingbacks manteniendo funcionales otros métodos XML-RPC.
- Sucuri: El Sucuri Web Application Firewall (basado en la nube) puede bloquear XML-RPC a nivel de CDN antes de que las peticiones lleguen siquiera a tu servidor.
Reglas de Cloudflare WAF para protección XML-RPC
Si usas Cloudflare, puedes crear una regla WAF que bloquee las peticiones XML-RPC en el edge, antes de que lleguen a tu servidor. Ve a Security > WAF > Custom Rules y crea una regla:
- Nombre de la regla: Block XML-RPC
- Expresión:
(http.request.uri.path contains "/xmlrpc.php") - Acción: Block
Este es el método de bloqueo más eficiente porque Cloudflare gestiona la petición en sus servidores edge. Tu servidor de origen nunca ve el tráfico. Si necesitas permitir Jetpack, añade una excepción para los rangos de IP de Automattic.
Configuración de fail2ban para fuerza bruta XML-RPC
Si gestionas tu propio servidor (VPS o dedicado), puedes usar fail2ban para banear automáticamente direcciones IP que golpean repetidamente xmlrpc.php. Crea un archivo de filtro en /etc/fail2ban/filter.d/wordpress-xmlrpc.conf:
[Definition]
failregex = ^<HOST> .* "POST .*xmlrpc.php.*" (200|403)
ignoreregex =Luego añade una jail en /etc/fail2ban/jail.local:
[wordpress-xmlrpc]
enabled = true
port = http,https
filter = wordpress-xmlrpc
logpath = /var/log/apache2/access.log
maxretry = 5
findtime = 60
bantime = 3600Esta configuración banea cualquier dirección IP que haga más de 5 peticiones a xmlrpc.php en 60 segundos, bloqueándolas durante una hora. Ajusta los valores según los patrones de tráfico de tu sitio.
XML-RPC vs. REST API: comparativa de seguridad
Entender por qué la REST API es más segura ayuda a explicar por qué XML-RPC debería retirarse:
- Autenticación: La REST API admite múltiples métodos de autenticación (cookie auth, contraseñas de aplicación, OAuth) y cuenta con verificación de nonce integrada. XML-RPC envía las credenciales en texto plano dentro del cuerpo XML en cada petición.
- Limitación de tasa: Las peticiones de la REST API pueden limitarse por endpoint. El método multicall de XML-RPC hace que la limitación de tasa por petición sea ineficaz.
- Permisos: La REST API respeta las comprobaciones de capacidades de WordPress y proporciona callbacks de permisos granulares para cada endpoint. XML-RPC tiene un control de acceso más burdo.
- Validación de entrada: Los endpoints de la REST API utilizan validación de entrada basada en esquemas. XML-RPC depende de las implementaciones de cada método individual para la validación.
- Sin equivalente de multicall: La REST API no dispone de un endpoint por lotes que permita agrupar cientos de intentos de autenticación en una sola petición.
Comprueba si todavía necesitas XML-RPC antes de deshabilitarlo
Antes de deshabilitar XML-RPC, verifica que ninguno de tus servicios activos lo requiera:
- Jetpack: Algunas funciones de Jetpack todavía se comunican vía XML-RPC. Si usas Jetpack, comprueba tu sitio tras deshabilitar XML-RPC. Si las funciones se rompen, puede que necesites permitir las direcciones IP de Automattic o usar el método de lista de permitidos a nivel de servidor mostrado arriba.
- App móvil de WordPress: Las versiones actuales de la app móvil de WordPress usan la REST API. Solo las versiones muy antiguas (anteriores a 2019) usaban XML-RPC. Si tu app funciona bien, no necesitas XML-RPC.
- Integraciones de IFTTT o Zapier: Algunas integraciones heredadas con servicios de automatización usaban XML-RPC. Comprueba si tus automatizaciones siguen funcionando tras deshabilitarlo.
- Windows Live Writer u otros editores de escritorio: Estas herramientas heredadas usaban XML-RPC para publicar. Si todavía usas alguna, considera cambiarte al editor de bloques de WordPress o a una alternativa basada en la REST API.
Verificar que XML-RPC está deshabilitado
Después de aplicar el método elegido, verifica que XML-RPC está realmente bloqueado:
# Debería devolver 403 Forbidden o conexión rechazada
curl -s -o /dev/null -w "%{http_code}" -X POST
https://tusitio.com/xmlrpc.php
-H "Content-Type: text/xml"
-d '<?xml version="1.0"?><methodCall><methodName>system.listMethods</methodName></methodCall>'Si obtienes un código de estado 403, XML-RPC está bloqueado. Si sigues obteniendo un 200, tu método de bloqueo no está funcionando correctamente. Revisa tu configuración y asegúrate de que el servidor se reinició (para Nginx) o de que los cambios en .htaccess están siendo leídos (para Apache, asegúrate de que AllowOverride está habilitado).
También puedes ejecutar un análisis con InspectWP. La sección de seguridad detecta si XML-RPC es accesible y lo marca como un riesgo potencial si responde a las peticiones.