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.multicallrequests with hundreds of method calls- Legitimate XML-RPC users (Jetpack, mobile apps) are blocked
- Server becomes slow or unresponsive during attacks
Real Log Entry
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 attemptsHow to Fix It
Fix 1: Disable XML-RPC Completely (If Not Needed)
// functions.php or mu-plugin
add_filter('xmlrpc_enabled', '__return_false');# .htaccess
<Files xmlrpc.php>
Order deny,allow
Deny from all
</Files># nginx.conf
location = /xmlrpc.php {
deny all;
access_log off;
log_not_found off;
return 444;
}Fix 2: Allow Only Specific IPs
# .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
// 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 ```