WordPress XML-RPC Brute Force Attack: How Hackers Slow Down Your Site Without You Knowing

Your WordPress site has been getting slower for the past two days. Pages that loaded in under a second now take five, sometimes ten seconds. You check your plugins, clear your cache, restart PHP. Nothing helps. You do not realise that someone is sending thousands of password attempts to a file you have never heard of.

The file that lets attackers try 500 passwords in one request

Every WordPress installation contains a file called xmlrpc.php in the root directory. It has been there since WordPress 3.5 — enabled by default, visible to anyone, and accepting POST requests from the entire internet. Most WordPress site owners have never heard of it, never configured it, and have no idea it is active.

XML-RPC was designed for a legitimate purpose: allowing remote publishing. Before the WordPress REST API existed, desktop blogging apps and mobile apps used XML-RPC to create and manage posts without logging into wp-admin. It also handled pingbacks — the notification system that tells you when another site links to your content.

The problem is a feature called system.multicall. This method allows multiple XML-RPC calls to be bundled into a single HTTP request. An attacker sends one POST request containing hundreds of wp.getUsersBlogs calls, each with a different username and password. WordPress obediently processes every single one — authenticating each attempt, hashing each password with bcrypt, querying the database, and returning the result.

One HTTP request. Five hundred login attempts. Your access logs show a single POST to xmlrpc.php. Your login attempt limiter counts it as one request and lets it through. But internally, your server just processed 500 authentication operations — each one consuming CPU time, memory, and a database query.

Now imagine the attacker sending 10 of these requests per second. That is 5,000 authentication attempts per second, all hitting your database with bcrypt hash comparisons. Your site does not crash immediately — it slows down. Your visitors experience 3-second load times, then 8-second load times, then timeouts. And you have no idea why.

Why XML-RPC attacks are worse than wp-login.php brute force

A traditional brute force attack on wp-login.php sends one login attempt per HTTP request. Each request triggers one authentication operation. Rate limiting plugins count each request and block the IP after a set number of failed attempts. The attack is visible in your access logs as thousands of POST requests to wp-login.php.

XML-RPC attacks bypass all of this. Here is why they are fundamentally more dangerous.

1. Amplification through system.multicall

A single HTTP request to xmlrpc.php can contain 500 or more wp.getUsersBlogs calls. Each call is a complete authentication attempt — WordPress loads the user from the database, hashes the provided password with bcrypt, and compares it to the stored hash. The CPU cost of bcrypt is intentionally high (that is the point of bcrypt — making brute force expensive). Multiply that by 500 and one HTTP request consumes as much CPU as 500 individual login attempts.

Login attempt limiting plugins like Limit Login Attempts Reloaded or Wordfence typically count HTTP requests, not internal authentication operations. They see one request to xmlrpc.php and count it as one attempt. The 500 authentication operations inside that request go uncounted and unblocked.

2. Invisible in standard access logs

Your web server access log shows one line for each HTTP request. An XML-RPC multicall attack generates far fewer log entries than a wp-login.php attack. If you are scanning logs for suspicious activity — looking for hundreds of POST requests to the login page — you will miss the XML-RPC attack entirely. It looks like a handful of POST requests to an XML file.

3. CPU exhaustion without visible errors

The attack does not cause immediate errors. Your site stays up, returns 200 status codes, and serves pages — just increasingly slowly. CPU usage climbs to 100% as bcrypt operations pile up. PHP workers that would normally serve your pages are stuck processing authentication attempts. New visitor requests wait in the queue. Response times climb from 500ms to 2 seconds to 5 seconds to 15 seconds.

On shared hosting, the hosting provider might throttle or suspend your account for excessive CPU usage — and you receive a warning email about your own site being a resource hog, not a notification that you are under attack.

4. DDoS amplification via pingback

XML-RPC's pingback feature can also be exploited for DDoS amplification. An attacker sends a pingback request to your xmlrpc.php asking it to verify a link on a target website. Your WordPress server makes an HTTP request to the target site on behalf of the attacker. By sending this request to thousands of WordPress sites simultaneously, the attacker uses those sites — including yours — as a DDoS botnet. Your server becomes an unwitting participant in an attack against someone else.

How to check if your site is under XML-RPC attack right now

Check your access logs

Look for POST requests to /xmlrpc.php in your web server access logs. On most Linux servers, the access log is at /var/log/apache2/access.log or /var/log/nginx/access.log. Filter for xmlrpc:

grep xmlrpc.php /var/log/apache2/access.log | tail -50

If you see dozens or hundreds of POST requests to xmlrpc.php from the same IP or multiple IPs, you are likely under attack. Legitimate XML-RPC usage generates very few requests — if you are not using a remote publishing tool, you should see zero.

Check server resource usage

Run top or htop on your server. If PHP or MySQL processes are consuming an abnormal amount of CPU, and your site is not experiencing a legitimate traffic spike, an XML-RPC attack may be the cause. Cross-reference the CPU spike timing with the xmlrpc.php requests in your access log.

Test if xmlrpc.php is accessible

Visit yourdomain.com/xmlrpc.phpin your browser. If you see "XML-RPC server accepts POST requests only," the endpoint is active and accessible. Anyone on the internet can send POST requests to it.

How to disable xmlrpc.php properly

Method 1: Block at the web server level (.htaccess)

The most effective approach is blocking access to xmlrpc.php before the request reaches PHP. This means WordPress never loads, no CPU is consumed processing the request, and the attack is stopped at the web server level.

For Apache, add this to your .htaccess file in the WordPress root directory:

<Files xmlrpc.php>
Order Deny,Allow
Deny from all
</Files>

For Nginx, add this to your server block:

location = /xmlrpc.php {
deny all;
return 403;
}

This returns a 403 Forbidden error for any request to xmlrpc.php without loading PHP at all. It is the lowest-overhead solution.

Method 2: Disable via WordPress filter

If you do not have access to your web server configuration, you can disable XML-RPC at the application level. Add this to your theme's functions.php or a custom plugin:

add_filter('xmlrpc_enabled', '__return_false');

This disables XML-RPC functionality but the file still loads. WordPress still bootstraps, PHP still executes, and some CPU is still consumed. This is less effective than blocking at the web server level but better than leaving XML-RPC fully active.

Method 3: Use a security plugin

Security plugins like Wordfence, iThemes Security, and Sucuri include options to disable XML-RPC. In Wordfence, go to Firewall > Brute Force Protection and enable "Block XML-RPC authentication attempts." This blocks the authentication-based attacks while still allowing non-authentication XML-RPC methods if needed.

The WordPress Hardening Guide provides additional security recommendations for protecting your WordPress installation against common attack vectors.

Method 4: Block at Cloudflare or WAF level

If your site is behind Cloudflare or another Web Application Firewall, create a rule to block all requests to /xmlrpc.php. In Cloudflare, go to Security > WAF > Custom Rules and create a rule where "URI Path equals /xmlrpc.php" with the action "Block." This stops the request at the edge before it ever reaches your server — zero CPU impact on your origin.

How to detect XML-RPC attacks with Uptrue before your site crashes

The dangerous thing about XML-RPC attacks is the gap between when the attack starts and when your site actually crashes. The attack might run for hours, gradually exhausting your server's resources, while your uptime monitor reports that everything is fine — because the site is still technically returning 200 status codes. It is just taking 15 seconds to do it.

Uptrue's HTTP monitoring tracks response time on every check. It does not just tell you whether your site is up or down — it tells you how fast your site is responding. When an XML-RPC attack starts consuming CPU and slowing your server, Uptrue detects the response time increase and alerts you before the site goes down.

Step 1: Set up an HTTP monitor with response time alerting

  1. Sign up at uptrue.io/signup (free plan available)
  2. Click Add Monitor from your dashboard
  3. Select HTTP/HTTPS as the monitor type
  4. Enter your homepage URL
  5. Set expected status to 200
  6. Set the check interval to 1 minute
  7. Configure alerts — Slack, email, or Microsoft Teams

Uptrue records response time on every check. When your site is healthy, response time is consistent — say 300ms to 800ms. During an XML-RPC attack, response time climbs steadily as PHP workers become occupied with authentication attempts. You will see the response time graph spike from hundreds of milliseconds to seconds. The alert fires when response time exceeds your threshold, giving you time to investigate and block the attack.

Step 2: Monitor xmlrpc.php directly

  1. Click Add Monitor again
  2. Select HTTP/HTTPS as the monitor type
  3. Enter yourdomain.com/xmlrpc.php as the URL
  4. Set expected status to 403 (if you have blocked it) or 405
  5. Set the interval to 5 minutes

If you have blocked xmlrpc.php at the server level, this monitor confirms the block is still active. If the expected status changes from 403 back to 200 (meaning the block was removed — perhaps by a WordPress update overwriting .htaccess or a server configuration change), Uptrue alerts you immediately. This prevents the attack surface from silently reopening.

Step 3: Monitor wp-login.php for parallel attacks

Attackers often run XML-RPC and wp-login.php brute force attacks simultaneously. While you are focused on the XML-RPC vector, the wp-login.php attack continues. Set up an additional HTTP monitor on your login page to detect response time spikes from concurrent brute force attempts. See our guide on WordPress brute force attacks for details on hardening wp-login.php.

Step 4: Configure escalating alerts

XML-RPC attacks can escalate from a performance degradation to a full outage within minutes. Your alerts need to match this urgency:

  • Slack — immediate notification when response time exceeds threshold
  • Microsoft Teams — for teams using Microsoft collaboration tools
  • Email — as a backup trail and for post-incident review
  • Webhook — integrate with PagerDuty or Opsgenie for phone alerts during off-hours

Check your WordPress site health right now

Instant health score across uptime, SSL, DNS, security headers, and performance. See if xmlrpc.php is exposed and catch vulnerabilities before attackers do.

Check Your Website Score

Hardening your site against XML-RPC attacks

Disabling xmlrpc.php is the first step. These additional measures create layers of defence against brute force attacks from all vectors.

Implement rate limiting at the server level

Configure your web server to rate-limit POST requests to both xmlrpc.php and wp-login.php. In Nginx, use the limit_req module. In Apache, use mod_evasive or mod_security. Rate limiting at the server level catches attacks before WordPress loads, reducing the CPU impact to nearly zero.

Use a Web Application Firewall

A WAF like Cloudflare, Sucuri, or AWS WAF blocks known attack patterns and malicious IPs at the edge. The requests never reach your server. Cloudflare's free plan includes basic WAF protection that is sufficient for most WordPress sites. The Pro plan includes more aggressive bot detection that stops automated attacks more effectively.

Enable two-factor authentication

Even if an attacker discovers valid credentials through a brute force attack, two-factor authentication prevents them from logging in. Use a plugin like WP 2FA or Wordfence Login Security to require a TOTP code from an authenticator app for all administrator and editor accounts.

Change the admin username

XML-RPC brute force attacks typically target the "admin" username because it is the WordPress default. If your admin username is "admin," every brute force attack is already half-successful — they have the username right and only need to guess the password. Change the admin username to something unique and non-obvious.

Monitor server resources alongside uptime

CPU and memory monitoring alongside HTTP monitoring gives you a complete picture. A response time spike alerts you to the symptom. High CPU usage confirms the cause. Together, they tell you exactly when an attack started, how severe it is, and whether your mitigations are working.

Stop discovering attacks from your hosting provider's warning email

Most WordPress site owners discover XML-RPC attacks in one of two ways: their hosting provider sends a warning about excessive CPU usage, or their site crashes and a visitor tells them. By either point, the damage is done. The attack has been running for hours, your server resources have been exhausted, and your visitors have experienced slow or broken pages.

Uptrue checks your site every 60 seconds and tracks response time on every check. When an XML-RPC attack starts degrading your site's performance, you see the response time climbing in real time. You get alerted when it crosses your threshold — while your site is still responding, while you can still log in and apply a fix, while your visitors are experiencing a slowdown rather than a complete outage.

Disable xmlrpc.php today. Set up response time monitoring. The next attack attempt will fail silently instead of silently succeeding.

Detect XML-RPC attacks before they crash your site

Free plan available. HTTP monitoring with response time tracking. Alerts on Slack, email, Teams, and webhook. No credit card required.

Frequently asked questions

What is xmlrpc.php in WordPress?

xmlrpc.php is a file in every WordPress installation that provides an XML-RPC API for remote communication. It was originally designed for remote publishing — allowing desktop blogging apps and mobile apps to create, edit, and delete posts without logging into wp-admin. It also handles pingbacks (notifications when another site links to yours) and provides an interface for third-party integrations. XML-RPC was critical before WordPress introduced the REST API in version 4.7, but most modern WordPress sites no longer need it. Despite this, xmlrpc.php is still present and active by default in every WordPress installation.

How does the system.multicall attack work on xmlrpc.php?

The XML-RPC protocol supports a method called system.multicall that allows multiple method calls to be bundled into a single HTTP request. An attacker sends one POST request to xmlrpc.php containing hundreds of wp.getUsersBlogs calls, each with a different username-password combination. WordPress processes every single call within that one request — authenticating each attempt against the database, hashing each password with bcrypt, and comparing it against the stored hash. A single HTTP request can trigger 500 or more authentication attempts internally. This bypasses login attempt limits that only count HTTP requests, and it generates enormous CPU and database load from what appears to be a single request in your access logs.

Will disabling xmlrpc.php break my WordPress site?

For most modern WordPress sites, disabling xmlrpc.php will not break anything. The WordPress REST API, introduced in WordPress 4.7, handles all the functionality that xmlrpc.php provided — remote publishing, mobile app access, and third-party integrations. However, a small number of plugins still require XML-RPC. The Jetpack plugin uses XML-RPC to communicate with WordPress.com servers. Some older mobile apps and desktop publishing tools rely on XML-RPC instead of the REST API. If you use Jetpack or a legacy publishing tool, test after disabling xmlrpc.php to verify nothing breaks. For everyone else, disabling it removes an attack surface with no functional impact.

Can monitoring detect an XML-RPC brute force attack?

Standard uptime monitoring that only checks for a 200 status code will not detect an XML-RPC attack until the site has already crashed. The attack causes gradual resource exhaustion — your site stays up but response times climb from hundreds of milliseconds to seconds, then tens of seconds. HTTP monitoring that tracks response time detects this progression. Uptrue records response time on every check and alerts you when it exceeds a threshold — catching the attack while your site is still responding but degraded, giving you time to block the attack before it causes a full outage.