Deluxe Blog Tips About Projects

Disabling XML-RPC in WordPress

While monitoring hits to this blog, I recognize that the file which received most hits is xmlrpc.php. I was surprise because I don’t use XML-RPC for remote access, posting at all. I guess the problem may comes from bots, spammers or even hackers. So I decided to disable XML-RPC completely and here is how I did that.

What is XML-RPC?

XML-RPC is a Remote Procedure Call (RPC) protocol which uses XML to encode its calls and HTTP as a transport mechanism. XML-RPC also refers generically to the use of XML for remote procedure call, independently of the specific protocol.

Briefly, you use XML-RPC when you want to do something remotely to your blog such as posting, viewing comments, etc.

How XML-RPC is used in WordPress?

By default, WordPress enables XML-RPC automatically! It creates an API for XML-RPC to let us interact (get, read, edit, post, etc.) posts, comments, taxonomies, media, users and even options which means everything!

But where you can find application of XML-RPC in WordPress? The answer is many places:

  • Pingback
  • JSON API
  • iPhone/Android app
  • Remote posting by Microsoft Word for example.
  • Your own apps, perhaps!

How to disable XML-RPC in WordPress

As I said earlier, enabling XML-RPC without knowing about its functionality is no different to open a backdoor for spammers and hackers. It sometimes just wastes your server/hosting resources. Disable it if you don’t need.

First of all, you need to turn off XML-RPC functionality in WordPress, using this code (you better put it in a functionality plugin):

add_filter( 'xmlrpc_enabled', '__return_false' );
add_filter( 'pings_open', '__return_false' );

This simple line tells WordPress to stop all remote requests using XML-RPC. But if you use a tool like curl to check HTTP headers, you still see the link to xmlrpc.php via the x-pingback header:

$ curl -I https://domain.com

HTTP/2 200 
date: Tue, 08 Nov 2022 03:33:05 GMT
content-type: text/html; charset=UTF-8
vary: Accept-Encoding
expires: Thu, 19 Nov 1981 08:52:00 GMT
cache-control: no-store, no-cache, must-revalidate
pragma: no-cache
x-pingback: https://domain.com/xmlrpc.php
link: <https://domain.com/wp-json/>; rel="https://api.w.org/"
link: <https://domain.com/wp-json/wp/v2/pages/2>; rel="alternate"; type="application/json"
link: <https://domain.com/>; rel=shortlink
set-cookie: PHPSESSID=o77s3ug23hms2uibe4v73tr1as; path=/; secure; HttpOnly

The present of xmlrpc.php in HTTP headers is a sign that tells spammers, bots that I’m still open a door for you. And you keep receiving hits to that door, even all hits are denied by WordPress. That wastes resources!

So, to hide xmlrpc.php in HTTP response headers, you need the following code (in a functionality plugin):

add_filter( 'wp_headers', 'yourprefix_remove_x_pingback' );
function yourprefix_remove_x_pingback( $headers ) {
    unset( $headers['X-Pingback'] );
    return $headers;
}

That’s enough for WordPress. From now spammers and bots don’t know URL to xmlrpc.php and if they guess correct URL, their requests are denied by WordPress.

But there’s still a room to improve the performance. Instead of making WordPress handles requests to xmlrpc.php, why don’t we make web server like Apache or nginx handle them? Requests will be denied in a lower layer of application, thus improving performance in general.

Denied requests to xmlrpc.php by Apache or nginx

To deny requests to xmlrpc.php in Apache, add this code to .htaccess file:

<IfModule mod_alias.c>
    RedirectMatch 403 /xmlrpc.php
</IfModule>

or

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

If you’re using nginx, this is the code you should add to server block:

server {
    location = /xmlrpc.php {
        deny all;
    }
}

That’s all. Your blog is fully protected from unexpected remote requests using XML-RPC. And hopefully it saves server resources and improve website performance.