Protect WordPress site from XML-RPC attack

Posted: 21 September 2016, Category: WordPress

Protect your WordPress site from XML-RPC attack

XML-RPC is a remote procedure call which uses XML to encode its calls and HTTP as a transport mechanism. It is a system that allows you to make posts to your WordPress blog using weblog clients. This means if you want to access and publish new content to your website remotely, you need XML-RPC enabled.

XML-RPC functionality was disabled by default in earlier WordPress versions, mainly due to security concerns. Since WordPress 3.5, however, XML-RPC functionality is turned on by default, and this has lead to a lot of problems.

Just a couple of months after the change was implemented, many developers reported massive DOS attacks against WordPress websites, where the XML-RPC script included in all WordPress installations was the apparent vulnerability.

All of these attacks and resulting server crashes are caused by XML-RPC functionality that nobody I know uses. So the only people benefiting from this "great" functionality are hackers trying to break into your website or crash your server by overloading it with requests, and spammers posting links to spammed sites, etc.

How do I know if XML-RPC functionality is disabled/enabled?

Determining whether your WordPress site is open to XML-RPC attack is as simple as visiting your site home-page and adding '/xmlrpc.php' to the end of the url such as:

      
  https://josefzacek.cz/xmlrpc.php
      

If you get 'Forbidden' error you are fine and there is no need to read the rest of this article unless you want to.

      
  Forbidden
  You don't have permission to access /xmlrpc.php on this server.
      

If you get a result like one below, you have XML-RPC functionality enabled and attacks on your WordPress website are possible.

      
  FXML-RPC server accepts POST requests only.
      

How do I find out if someone is running an XML-RPC attack on my WordPress site?

Your best friend is 'access.log' located at '/var/log/apache2' folder which records all requests processed by the server. If you see something similar to below, you have been targeted with XML-RPC attack.

      
  185.106.92.160 - - [18/Apr/2015:27:14:07 +0000] "POST /xmlrpc.php HTTP/1.0" 403 495 "-" "Mozilla/4.0 (compatible: MSIE 7.0; Windows NT 6.0)"
  185.106.92.160 - - [18/Apr/2015:27:14:22 +0000] "POST /xmlrpc.php HTTP/1.0" 403 495 "-" "Mozilla/4.0 (compatible: MSIE 7.0; Windows NT 6.0)"
  185.106.92.160 - - [18/Apr/2015:27:14:59 +0000] "POST /xmlrpc.php HTTP/1.0" 403 495 "-" "Mozilla/4.0 (compatible: MSIE 7.0; Windows NT 6.0)"
  185.106.92.160 - - [18/Apr/2015:27:15:52 +0000] "POST /xmlrpc.php HTTP/1.0" 403 495 "-" "Mozilla/4.0 (compatible: MSIE 7.0; Windows NT 6.0)"
  185.106.92.160 - - [18/Apr/2015:27:16:01 +0000] "POST /xmlrpc.php HTTP/1.0" 403 495 "-" "Mozilla/4.0 (compatible: MSIE 7.0; Windows NT 6.0)"
  185.106.92.160 - - [18/Apr/2015:27:15:52 +0000] "POST /xmlrpc.php HTTP/1.0" 403 495 "-" "Mozilla/4.0 (compatible: MSIE 7.0; Windows NT 6.0)"
  185.106.92.160 - - [18/Apr/2015:27:16:01 +0000] "POST /xmlrpc.php HTTP/1.0" 403 495 "-" "Mozilla/4.0 (compatible: MSIE 7.0; Windows NT 6.0)"
      

How do I prevent XML-RPC attacks?

1. Use a plugin

Disable XML-RPC plugin completely disables the XML-RPC functionality on your WordPress website. The problem is that web crawling bots can still target '/xmlrpc.php' file on your server and cause excessive load. This method must therefore be considered dangerous, and at best is only a partial solution.

Jetpack plugin uses Protect module which also claims to protect agains Brute force attacks against XML-RPC functionality.


2. Theme Functions

Adding a filter is another way to prevent XML-RPC attacks, but this method cannot be highly recommended as you will need to to this every time you implement a new theme, and at some stage you will probably forget to add

      
  add_filter('xmlrpc_enabled', '__return_false');
      

to your theme’s 'functions.php' file. Some developers have also reported that this approach does not always work, and that server load can remain high even in the presence of a filter. Server setup may play an important factor in these cases.


3. Apache .htaccess file

This is the method I use when my site is hosted on an Apache server, as modifying .htaccess as follows will deny access to the 'xmlrpc.php' file.

      
  <files xmlrpc.php>
    order allow,deny
    deny from all
  </files>
  
  RewriteRule ^xmlrpc.php$ "http://0.0.0.0/" [R=301,L]
      

I have implemented this solution many times on different servers and it has worked on all occasions. Note that .(dot) files are hidden by default on Unix/Linux systems and location of '.htaccess' file is in the root folder for the website.


5. NGINX server block

The very popular NGINX does not come with '.htaccess' file, it uses server block/s. Preventing XML-RPC attack on an NGINX server can be done by placing the following code inside the server block

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

The location of the server-block file depends on your server setup, but in most cases it is located in

      
  etc/nginx/sites-available
      

Test XML-RPC using curl command

Open your terminal (or iTerm2 in my case) and paste code below, substituting in the name of you site for 'www.josefzacek.cz'

    
$ curl -D -  "www.josefzacek.cz/xmlrpc.php" -d '<methodCall><methodName>pingback.ping</methodName><params><param><value><string>www.josefzacek.cz/blog/rails-4-directory-structure/</string></value></param></params></methodCall>'
    

if you get response similar to one below you are fine

    
  HTTP/1.1 301 Moved Permanently
  Server: nginx/1.10.1
  Date: Thu, 15 Sep 2016 21:12:15 GMT
  Content-Type: text/html
  Content-Length: 185
  Connection: keep-alive
  Location: https://www.josefzacek.cz/xmlrpc.php
  Strict-Transport-Security: max-age=31536000
    
  <html>
  <head><title>301 Moved Permanently</title></head>
  <body bgcolor="white">
  <center><h1>301 Moved Permanently</h1></center>
  <hr><center>nginx/1.10.1</center>
  </body>
  </html>
    

however if you get response similar to one below you still have XMl-RPC functionality enabled

    
  HTTP/1.1 200 OK
  Date: Thu, 15 Sep 2016 21:11:23 GMT
  Server: Apache
  X-Powered-By: PHP/5.5.38
  Connection: close
  X-SERVER: 2905
  Content-Length: 370
  Content-Type: text/xml; charset=UTF-8

  <?xml version="1.0" encoding="UTF-8"?>
  <methodResponse>
    <fault>
      <value>
        <struct>
          <member>
            <name>faultCode</name>
            <value><int>0</int></value>
          </member>
          <member>
            <name>faultString</name>
            <value><string></string></value>
          </member>
        </struct>
      </value>
    </fault>
  </methodResponse>
    

When testing XML_RPC functionality you need to look out for 403 Forbidden messages in the output. A 403 Forbidden message means that XML-RPC is disabled in your WordPress site.

Overloading system resource is one of the most common reasons why your WordPress site go offline on both Shared web hosting service or Virtual private server (VPS). The last two methods (Apache and Nginx) of preventing XML-RPC attacks mentioned in this article will ensure your WordPress site stays protected from XML-RPC attacks.

If you come across web hosting company or developer telling you to simply delete the 'xmlrpc.php', my strong recommendation is to ignore such advice. Although it sounds like a good idea, it is dangerous as the 'xmlprc.php' file will be regenerated whenever you update WordPress.

Reference

Back to Blog page

Blog categories

Twitter feed

(8 days ago)
Flexbox Zombies is hands down the best way to master flexbox. https://t.co/sYxfDkv9Sl


(9 days ago)
Charts with Chartkick and Groupdate https://t.co/24N7JiZvkk


(9 days ago)
I'm absolutely loving Flexbox Zombies! https://t.co/sYxfDkv9Sl


(9 days ago)
The WPSetup Attack: New Campaign Targets Fresh WordPress Installs https://t.co/AlV1Gh0evG via @wordfence


Top of page