The Problem

The WordPress XML-RPC endpoint (xmlrpc.php) is a common target for brute force login attacks and pingback DDoS attacks. Attackers can send hundreds of authentication attempts in a single HTTP request, exhausting server resources.

Symptoms

  • High CPU and memory usage from php-fpm processes
  • Access logs show repeated POST requests to xmlrpc.php
  • system.multicall requests with hundreds of method calls
  • Legitimate XML-RPC users (Jetpack, mobile apps) are blocked
  • Server becomes slow or unresponsive during attacks

Real Log Entry

bash
185.220.101.45 - - [09/Apr/2026:03:15:22 +0000]
"POST /xmlrpc.php HTTP/1.1" 200 45823
"system.multicall" with 500 wp.getUsersBlogs attempts

How to Fix It

Fix 1: Disable XML-RPC Completely (If Not Needed)

php
// functions.php or mu-plugin
add_filter('xmlrpc_enabled', '__return_false');
apache
# .htaccess
<Files xmlrpc.php>
  Order deny,allow
  Deny from all
</Files>
nginx
# nginx.conf
location = /xmlrpc.php {
  deny all;
  access_log off;
  log_not_found off;
  return 444;
}

Fix 2: Allow Only Specific IPs

apache
# .htaccess
<Files xmlrpc.php>
  Order deny,allow
  Deny from all
  Allow from 192.168.1.100    # Your Jetpack server IP
  Allow from 203.0.113.50      # Your mobile app IP
</Files>

Fix 3: Rate Limit XML-RPC Requests

```nginx # nginx.conf - Rate limit limit_req_zone $binary_remote_addr zone=xmlrpc:10m rate=5r/m;

location = /xmlrpc.php { limit_req zone=xmlrpc burst=1 nodelay; fastcgi_pass unix:/run/php/php8.2-fpm.sock; } ```

Fix 4: Block system.multicall Specifically

php
// functions.php
add_filter('xmlrpc_methods', function($methods) {
  // Remove the multicall method used for brute force
  unset($methods['system.multicall']);
  // Remove pingback (used for DDoS)
  unset($methods['pingback.ping']);
  return $methods;
});

Fix 5: Monitor and Block Attacking IPs

```bash # Find top attacking IPs grep "POST /xmlrpc.php" /var/log/nginx/access.log | \ awk '{print $1}' | sort | uniq -c | sort -rn | head -20

# Block an IP ufw deny from 185.220.101.45

# Or in iptables iptables -A INPUT -s 185.220.101.45 -j DROP ```

Fix 6: Use Fail2Ban for XML-RPC

```ini # /etc/fail2ban/filter.d/wordpress-xmlrpc.conf [Definition] failregex = ^<HOST> .* "POST /xmlrpc.php ignoreregex =

# /etc/fail2ban/jail.local [wordpress-xmlrpc] enabled = true filter = wordpress-xmlrpc logpath = /var/log/nginx/access.log maxretry = 3 bantime = 3600 findtime = 60 ```

Fix 7: Verify XML-RPC is Disabled

```bash # Test if XML-RPC is accessible curl -I https://example.com/xmlrpc.php

# Should return 403 Forbidden or 444 ```