XML-RPC can pose serious security risks in WordPress. Understand the threats and learn advanced techniques to prevent brute-force and DDoS attacks.
Open the access log on almost any WordPress site and you’ll find them: a slow, patient drip of POST requests to xmlrpc.php from IPs you’ve never seen. That file has shipped with WordPress since the early days. Most of us never think about it. Attackers think about it a lot.
XML-RPC is a remote procedure call protocol. It encodes a request in XML and sends it over HTTP so software can talk to your site without a browser. Desktop publishing tools used it. Older mobile apps used it. Pingbacks between blogs run on it, and Jetpack still uses it for part of its connection to WordPress.com. Useful stuff. It’s also a door, and doors get knocked on.
So let’s walk through what this endpoint actually does, the two ways it gets abused (bulk brute-force logins and pingback-reflected DDoS), and how to close it off without breaking anything you still rely on. We’ll keep the fixes concrete and the caveats honest.
Table of Contents
- What Is XML-RPC in WordPress?
- How XML-RPC Works
- XML-RPC Brute Force Attacks
- XML-RPC DDoS Attacks
- How to Secure Your WordPress Site from XML-RPC Attacks
- Advanced Mitigation Strategies
- Conclusion
What Is XML-RPC in WordPress?
XML-RPC has been part of WordPress since close to the beginning. It lets external applications manage content, upload media, and publish posts without ever logging into wp-admin. Handy when your writing tool or a remote service needs to reach in and do work.
It’s enabled by default on every install. That default made sense when remote publishing had no other option. Since WordPress 4.7 in 2016, the REST API covers most of those jobs, and the current WordPress and Jetpack mobile apps authenticate over REST using application passwords. So a modern, up-to-date site usually doesn’t need xmlrpc.php for the app at all. One honest exception: Jetpack still talks to WordPress.com over XML-RPC for some features, so check what you actually run before you decide the file is dead weight.
How XML-RPC Works
The transport is plain HTTP; the payload is XML. A request moves through three steps:
- The client sends a request: a remote tool posts an XML-encoded request to your site’s XML-RPC endpoint.
- WordPress processes it: the request is handed to the matching method, which runs the action, whether that’s publishing a post or checking a set of credentials.
- WordPress returns a response: an XML-encoded reply goes back to the client.
Here’s the catch. The same endpoint that happily accepts a legitimate publish request will just as happily accept a hostile one. Nothing in the protocol tells your writing app apart from a script grinding through a password list.
XML-RPC Brute Force Attacks
The most common abuse is credential guessing. The workhorse method is wp.getUsersBlogs: hand it a username and password, and a valid pair returns that user’s blogs while a wrong pair returns a fault. That yes/no answer is all a script needs. Other authenticated methods like wp.getPost behave the same way, which turns xmlrpc.php into a login oracle that never shows a login form.
How the Attack Works
The attacker aims a method call at the XML-RPC endpoint and reads the response to learn whether the credentials worked. A bare-bones attempt against the user admin looks like this:
<?php
/**
* Example XML-RPC request for brute-force attack
*/
$request = xmlrpc_encode_request(
'wp.getUsersBlogs',
array('admin', 'password123')
);
// Send request to XML-RPC endpoint
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://yoursite.com/xmlrpc.php');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $request);
$response = curl_exec($ch);
curl_close($ch);Swap the password, send it again, repeat. On its own that’s just slow, noisy guessing. What makes XML-RPC worth an attacker’s time is the amplifier described in the next section.
Why XML-RPC Brute Force Attacks Are Dangerous
- One request, many guesses: with the
system.multicallmethod, an attacker can pack roughly a thousand login checks into a single HTTP request. Cloudflare and Sucuri both documented this; loop it and you reach a million attempts fast. - It slips past login defenses: a lot of rate limiting and lockout logic watches wp-login.php, not xmlrpc.php. Thousands of guesses can arrive as a handful of requests, well under the radar of anything counting failed page loads.
XML-RPC DDoS Attacks
XML-RPC turns up in denial-of-service attacks in two very different ways. One makes your own server do too much work. The other is nastier: it turns your site into a weapon pointed at someone else.
How XML-RPC Amplifies DDoS Attacks
The system.multicall method lets a client run many method calls inside one request. That’s the same batching trick from the brute-force section, and it’s the honest headline use: cram a thousand credential checks into a single call. Aim enough of those batches at your own server and the work of processing them can tie things up.
A system.multicall payload is built like this:
<?php
/**
* Example XML-RPC request for DDoS attack using system.multicall
*/
$multi_request = xmlrpc_encode_request(
'system.multicall',
array(
array('wp.getUsersBlogs', array('admin', 'password123')),
array('wp.getPost', array('admin', 'password123')),
// Add more method calls here
)
);
// Send the request to the XML-RPC endpoint
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://yoursite.com/xmlrpc.php');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $multi_request);
$response = curl_exec($ch);
curl_close($ch);Repeated from many sources at once, requests like this can bog a server down. But XML-RPC’s signature DDoS trick doesn’t target your site at all. For that, look at pingbacks.
The Pingback Reflection Attack
Pingbacks are unauthenticated by design, and that’s the problem. An attacker sends a pingback.ping request to thousands of ordinary WordPress sites with the “source” URL set to a victim’s server. Each of those innocent sites dutifully fetches the victim to verify the link. Thousands do it at once, and the victim drowns in traffic from real WordPress installs, yours possibly among them. Sucuri once traced a single attack of this kind back to more than 162,000 WordPress sites. This is the detail the plain “just disable XML-RPC” advice usually skips: pingbacks need no login, so switching off the authenticated methods doesn’t touch them.
How to Secure Your WordPress Site from XML-RPC Attacks
Good news: you have several ways to shut this down, from a one-liner to a server-level block. Match the fix to how much of XML-RPC you actually use.
1. Disable XML-RPC
If nothing on your site needs XML-RPC, turn it off. The one-line filter drops into your theme’s functions.php (or, better, a small site-specific plugin):
<?php
/**
* Disable XML-RPC in WordPress
*/
add_filter('xmlrpc_enabled', '__return_false');
Read the fine print, though. Per the WordPress documentation, the xmlrpc_enabled filter only switches off the methods that require authentication, the publishing and editing calls. It does not disable pingbacks or other unauthenticated methods, and xmlrpc.php still loads and answers requests. So the filter stops the brute-force logins but leaves the pingback reflection door open.
To close the file completely, block it at the web server so a request never reaches WordPress. On Apache, drop this into your .htaccess:
<?php
# Block all external access to xmlrpc.php
<Files xmlrpc.php>
Order Deny,Allow
Deny from all
</Files>
On Nginx you’d deny location = /xmlrpc.php instead. Either way the server returns a 403 before any PHP runs, which shuts the brute-force and pingback vectors at the same time. If one client genuinely still needs XML-RPC, allow its IP through and deny everyone else.
2. Use a Security Plugin
If you can’t disable XML-RPC outright, a security plugin will fence it in. Wordfence, already common on WordPress sites, rate-limits XML-RPC authentication and can switch the interface off entirely; Sucuri and similar tools do the same. It’s less absolute than a server block, but it’s a solid choice when you need some XML-RPC methods alive.
3. Use a Web Application Firewall (WAF)
A Web Application Firewall (WAF) sits in front of your site and inspects traffic before it reaches WordPress. A good one recognizes the multicall brute-force pattern and the pingback flood and drops them at the edge, which also spares your origin server the load. Cloudflare, Sucuri, and most managed-WordPress hosts offer this.
Advanced Mitigation Strategies
Bigger or higher-traffic sites usually layer a few more defenses on top:
- Rate limiting: cap how many XML-RPC requests a single IP can make per minute, so no one source can flood the endpoint.
- Cover the endpoint, not just the login form: two-factor auth and CAPTCHA on wp-login.php do nothing for XML-RPC, because XML-RPC never touches that form. Make sure whatever protection you add actually applies to
xmlrpc.php, or block the file and skip the problem. - IP allowlisting: if only a known service or two need XML-RPC, permit those addresses and deny the rest.
Conclusion
For most sites the honest answer is simple: you’re not using XML-RPC, so block xmlrpc.php at the server and be done with it. That one move closes the brute-force amplifier and the pingback reflection trick in a single stroke.
If you do run something that needs it, like Jetpack’s WordPress.com link or an older workflow, don’t leave the endpoint wide open. Disable the authenticated methods you don’t use, lock down pingbacks, and let Wordfence or a WAF rate-limit what’s left. XML-RPC isn’t evil; it’s just an old door a lot of sites forgot they left unlocked. Check yours, decide what you actually need, and shut the rest.


