Tutorial

How To Protect WordPress from XML-RPC Attacks on Ubuntu 14.04

How To Protect WordPress from XML-RPC Attacks on Ubuntu 14.04

Introduction

WordPress is a popular and powerful CMS (content management system) platform. Its popularity can bring unwanted attention in the form of malicious traffic specially targeted at a WordPress site.

There are many instances where a server that has not been protected or optimized could experience issues or errors after receiving a small amount of malicious traffic. These attacks result in exhaustion of system resources causing services like MySQL to be unresponsive. The most common visual cue of this would be an Error connecting to database message. The web console may also display Out of Memory errors.

This guide will show you how to protect WordPress from XML-RPC attacks on an Ubuntu 14.04 system.

Prerequisites

For this guide, you need the following:

We assume you already have WordPress installed on an Ubuntu 14.04 Droplet. There are many ways to install WordPress, but here are two common methods:

All the commands in this tutorial should be run as a non-root user. If root access is required for the command, it will be preceded by sudo. Initial Server Setup with Ubuntu 14.04 explains how to add users and give them sudo access.

What is XML-RPC?

WordPress utilizes XML-RPC to remotely execute functions. The popular plugin JetPack and the WordPress mobile application are two great examples of how WordPress uses XML-RPC. This same functionality also can be exploited to send thousands of requests to WordPress in a short amount of time. This scenario is effectively a brute force attack.

Recognizing an XML-RPC Attack

The two main ways to recognize an XML-RPC attack are as follows:

  1. Seeing the “Error connecting to database” message when your WordPress site is down
  2. Finding many entries similar to "POST /xmlrpc.php HTTP/1.0” in your web server logs

The location of your web server log files depends on what Linux distribution you are running and what web server you are running.

For Apache on Ubuntu 14.04, use this command to search for XML-RPC attacks:

  1. grep xmlrpc /var/log/apache2/access.log

For Nginx on Ubuntu 14.04, use this command to search for XML-RPC attacks:

  1. grep xmlrpc /var/log/nginx/access.log

Your WordPress site is receiving XML-RPC attacks if the commands above result in many lines of output, similar to this example:

access.log
111.222.333.444:80 555.666.777.888 - - [01/Jan/2016:16:33:50 -0500] "POST /xmlrpc.php HTTP/1.0" 200 674 "-" "Mozilla/4.0 (compatible: MSIE 7.0; Windows NT 6.0)"

The rest of this article focuses on three different methods for preventing further XML-RPC attacks.

Method 1: Installing the Jetpack Plugin

Ideally, you want to prevent XML-RPC attacks before they happen. The Jetpack plugin for WordPress can block the XML-RPC multicall method requests with its Protect function. You will still see XML-RPC entries in your web server logs with Jetpack enabled. However, Jetpack will reduce the load on the database from these malicious log in attempts by nearly 90%.

Note: A WordPress.com account is required to activate the Jetpack plugin.

Jetpack installs easily from the WordPress backend. First, log into your WordPress control panel and select Plugins->Add New in the left menu.

WordPress Plugins Menu

Jetpack should be automatically listed on the featured Plugins section of the Add New page. If you do not see it, you can search for Jetpack using the search box.

Jetpack Install Page

Click the Install Now button to download, unpack, and install Jetpack. Once it is successfully installed, there will be an Activate Plugin link on the page. Click that Activate Plugin link. You will be returned to the Plugins page and a green header will be at the top that states Your Jetpack is almost ready!. Click the Connect to Wordpress.com button to complete the activation of Jetpack.

Connect to Wordpress.com button

Now, log in with a WordPress.com account. You can also create an account if needed.

Log into Wordpress.com form

After you log into your WordPress.com account, Jetpack will be activated. You will be presented with an option to run Jump Start which will automatically enable common features of Jetpack. Click the Skip link at this step.

Jump Start Screen.

The Protect function is automatically enabled, even if you skip the Jump Start process. You can now see a Jetpack dashboard which also displays the Protect function as being Active. White list IP addresses from potentially being blocked by Protect by clicking the gear next to the Protect name.

Jetpack Dashboard

Enter the IPv4 or IPv6 addresses that you want to white list and click the Save button to update the Protect white list.

Protect Settings

Method 2: Enabling block-xmlrpc with a2enconf

The a2enconf block-xmlrpc feature was added to the DigitalOcean WordPress one-click image in December of 2015. With it, you can block all XML-RPC requests at the web server level.

Note: This method is only available on a DigitalOcean One-Click WordPress Install created in December 2015 and later.

To enable the XML-RPC block script, run the following command on your Droplet with the DO WordPress one-click image installed:

  1. sudo a2enconf block-xmlrpc

Restart Apache to enable the change:

  1. sudo service apache2 restart

Warning: This method will stop anything that utilizes XML-RPC from functioning, including Jetpack or the WordPress mobile app.

Method 3: Manually Blocking All XML-RPC Traffic

Alternatively, the XML-RPC block can manually be applied to your Apache or Nginx configuration.

For Apache on Ubuntu 14.04, edit the configuration file with the following command:

  1. sudo nano /etc/apache2/sites-available/000-default.conf

Add the highlighted lines below between the <VirtualHost> tags.

Apache VirtualHost Config
<VirtualHost>
…    
    <files xmlrpc.php>
      order allow,deny
      deny from all
    </files>
</VirtualHost>

Save and close this file when you are finished.

Restart the web server to enable the changes:

  1. sudo service apache2 restart

For Nginx on Ubuntu 14.04, edit the configuration file with the following command (change the path to reflect your configuration file):

  1. sudo nano /etc/nginx/sites-available/example.com

Add the highlighted lines below within the server block:

Nginx Server Block File
server {
…
 location /xmlrpc.php {
      deny all;
    }
}

Save and close this file when you are finished.

Restart the web server to enable the changes:

  1. sudo service nginx restart

Warning: This method will stop anything that utilizes XML-RPC from functioning, including Jetpack or the WordPress mobile app.

Verifying Attack Mitigation Steps

Whatever method you chose to prevent attacks, you should verify that it is working.

If you enable the Jetpack Protect function, you will see XML-RPC requests continue in your web server logs. The frequency should be lower and Jetpack will reduce the load an attack can place on the database server process. Jetpack will also progressively block the attacking IP addresses.

If you manually block all XML-RPC traffic, your logs will still show attempts, but the resulting error code be something other than 200. For example entries in the Apache access.log file may look like:

access.log
111.222.333.444:80 555.666.777.888 - - [01/Jan/2016:16:33:50 -0500] "POST /xmlrpc.php HTTP/1.0" 500 674 "-" "Mozilla/4.0 (compatible: MSIE 7.0; Windows NT 6.0)"

Conclusion

By taking steps to mitigate malicious XML-RPC traffic, your WordPress site will consume less system resources. Exhausting system resources is the most common reason why a WordPress site would go offline on a VPS. The methods of preventing XML-RPC attacks mentioned in this article along with will ensure your WordPress site stays online.

To learn more about brute force attacks on WordPress XML-RPC, read Sucuri.net — Brute Force Amplification Attacks Against WordPress XMLRPC.

Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.

Learn more about our products

About the author(s)

Still looking for an answer?

Ask a questionSearch for more help

Was this helpful?
 
10 Comments
Leave a comment...

This textbox defaults to using Markdown to format your answer.

You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!

Any problems with use of htaccess method?

BEGIN protect xmlrpc.php

<files xmlrpc.php> order allow,deny deny from all </files>

END protect xmlrpc.php

[]'s

Eris Castrogivanni
DigitalOcean Employee
DigitalOcean Employee badge
February 21, 2016

That’ll work too, but will have the same effect as blocking it in your Apache or Nginx config - Jetpack and other XML-RPC dependent plugins will no longer work. If that’s okay with you, then this is a good method to block access to that file.

XML-RPC DDoS Protection for Web Servers with ModSecurity and Iptables

Victim’s Web Server under XML-RPC DDoS attack:

213.189.55.149 victim.com- [29/Jun/2015:12:50:35 +0700] "GET /index.php HTTP/1.0" 400 1905 "-" "WordPress/3.9.6; http://www.gamesbase24.com; verifying pingback from 54.169.67.213" 5.001
194.58.92.216 victim.com - [29/Jun/2015:13:11:51 +0700] "GET / HTTP/1.0" 400 1905 "-" "WordPress/3.5; http://mygoldpartners.ru" 5.001

Mitigation

ModSecurity rule:

SecAction "id:1,phase:1,t:none,pass,nolog,initcol:global=global,initcol:ip=%{remote_addr}"
SecRule REQUEST_HEADERS:User-Agent "(wordpress|pingback)" "id:12,phase:1,t:lowercase,exec:/etc/exec/pingback.sh,deny,status:400"

Pingback.sh:


#!/bin/bash
/bin/echo +$REMOTE_ADDR >/proc/net/xt_recent/PINGBACK

Iptables rule:

-A INPUT -p tcp -m tcp --dport 80 -m recent --update --seconds 2592000 --hitcount 1 --name PINGBACK --rsource -j DROP

If you are using Nginx, add it to VirtualHost config

if ($http_user_agent ~* (WorPress|pingback) ) {
        return 444;
}

Source: http://forum.ceh.vn/Bao-toan-server-truoc-cuoc-DDOS-thong-qua-lo-hong-xmlrpcphp-cua-WordPress-thread-7330.ceh

alexdo
Site Moderator
Site Moderator badge
November 28, 2024

Thanks for sharing this!

This strategy can be very effective for defending against XML-RPC-based DDoS attacks. It’s especially useful for blocking smaller, targeted attacks. However, for large-scale attacks or if your traffic scales significantly, consider integrating a WAF service to offload the attack filtering and prevent potential performance bottlenecks.

Regards

Blocking XML-RPC is a great move for 99% of WordPress sites. However, installing the Jetpack plugin is generally a bad idea and will cause added performance and security issues.

https://www.littlebizzy.com/blog/disable-xml-rpc

location = /xmlrpc.php {
    deny all;
    }

The above “equals” sign may be necessary to deny requests to the xmlrpc.php file, and is truly the only smart way to disable it. Plugins and application-level blocking is only asking for trouble as it can be circumvented, depends on your site stability, and so forth.

Eris Castrogivanni
DigitalOcean Employee
DigitalOcean Employee badge
February 21, 2016

It really depends. I haven’t seen much of a performance hit with using Jetpack solely for its Protect module. If you leave the other modules inactive, it isn’t a big issue. On top of that, Jetpack is maintained by Automattic, and is one of the most secure WordPress plugins out there. Installing any plugin is a security and performance risk. Using WordPress itself can be a security and performance risk. But Jetpack is one of the better ones out there.

I couldn’t figure out why I was still getting a 200 response after following this guide. Adding the equals sign did it for me.

alexdo
Site Moderator
Site Moderator badge
November 28, 2024

Heya,

Using the = in the location block creates an exact match for the path, but it is not strictly necessary if you just want to deny access to /xmlrpc.php regardless of whether the URL is exactly or partially matched.

If you want to block access to all requests that involve /xmlrpc.php without worrying about exact matches, your original configuration would work just fine without the =

Regards

So far our site was attacked from a small number of IPs, not a full-scale botnet, and we’ve had one short interval of downtime. So instead, I blocked more than 2 consecutive retries using fail2ban with a long bantime, only slightly modified from an answer on stackoverflow or somewhere similar:

/etc/fail2ban/filter.d/xmlrpc.conf (new file)

[Definition]
failregex = ^<HOST> .*POST .*xmlrpc\.php.*
ignoreregex =

/etc/fail2ban/jail.local (appended to the existing file)

[xmlrpc]
enabled = true
filter = xmlrpc
action = iptables[name=xmlrpc, port=http, protocol=tcp]
logpath = /var/log/apache2/access.log
bantime = 600000
maxretry = 2
findtime = 6000

This works like a charm. The question is: is this a robust enough solution if our traffic scales up? I wnated to avoid blocking the file completely as it might be important for WP functionality.

alexdo
Site Moderator
Site Moderator badge
November 28, 2024

Your current Fail2Ban setup is a good solution for blocking XML-RPC abuse while keeping xmlrpc.php accessible for legitimate use. However, if your site grows and faces more traffic, you should consider:

  • Offloading the blocking to a WAF or hardware firewall.
  • Implementing rate limiting to control traffic to xmlrpc.php without full blocking.
  • Regularly monitoring Fail2Ban performance and scaling it appropriately.

For now, your setup is perfectly fine for moderate traffic, but these considerations will help future-proof your site against larger-scale attacks.

Let me know if you want help setting up any of these advanced protections!

Hi,

I suspect the method 2 “Enabling block-xmlrpc with a2enconf” does not work!

These are the steps I did. Step 1. Rebuilt my droplet with “One-Click Install WordPress on Ubuntu 14.04”. Step 2. Updated Ubuntu Step 3. Setup wordpress Step 4. Run “sudo a2enconf block-xmlrpc”, I got these warnings:

perl: warning: Setting locale failed.
perl: warning: Please check that your locale settings:
LANGUAGE = (unset),
LC_ALL = (unset),
LC_CTYPE = "UTF-8",
LANG = "en_US.UTF-8"
are supported and installed on your system.
perl: warning: Falling back to the standard locale ("C").
Enabling conf block-xmlrpc.
To activate the new configuration, you need to run:
service apache2 reload

Please note that there is “Enabling conf block-xmlpc”.

Step 5. After some hours, I still got http status code of 200. First 6 entries are listed below. Two of them are 200. Others are 301.

5.178.68.254 - - [10/Mar/2016:11:46:01 -0500] "POST /xmlrpc.php HTTP/1.1" 301 573 "http://bb.com/xmlrpc.php" "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.11) Gecko/20070502 Firefox/1.5.0.11 Flock/0.7.13.1"
5.178.68.254 - - [10/Mar/2016:11:46:42 -0500] "POST / HTTP/1.1" 200 6163 "http://bb.com/xmlrpc.php" "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.11) Gecko/20070502 Firefox/1.5.0.11 Flock/0.7.13.1"
89.47.29.92 - - [10/Mar/2016:12:21:53 -0500] "POST /xmlrpc.php HTTP/1.0" 301 524 "http://www.hh.com/" "PHP/5.2.03"
75.103.70.22 - - [10/Mar/2016:15:20:45 -0500] "POST /xmlrpc.php HTTP/1.0" 301 512 "-" "-"
5.178.68.254 - - [10/Mar/2016:15:38:58 -0500] "POST /xmlrpc.php HTTP/1.1" 301 573 "http://bb.com/xmlrpc.php" "Mozilla/5.0 (X11; U; Linux x86_64; es-ES; rv:1.9.1.8) Gecko/20100216 Fedora/3.5.8-1.fc11 Firefox/3.5.8"
5.178.68.254 - - [10/Mar/2016:15:39:44 -0500] "POST / HTTP/1.1" 200 6165 "http://bb.com/xmlrpc.php" "Mozilla/5.0 (X11; U; Linux x86_64; es-ES; rv:1.9.1.8) Gecko/20100216 Fedora/3.5.8-1.fc11 Firefox/3.5.8"

(I changed the domain names above for privacy reason.)

Step 6. Finally I rebuilt the droplet again, and this time with method 3 “Manually Blocking All XML-RPC Traffic”. Now all I got are 403.

My question is: Does method 2 work? It seems it is NOT working! I created a ticket for support and they also believe it is not working too.

ps: I tried many fixes to locale warning, but the problem is still there.

alexdo
Site Moderator
Site Moderator badge
November 28, 2024

After running a2enconf block-xmlrpc, the block rule should be enabled. You need to ensure that the configuration file is correctly applied. Let’s go through some checks:

  • Verify Configuration File: Ensure that the file /etc/apache2/conf-available/block-xmlrpc.conf exists and contains the necessary directives to block XML-RPC. The file should have something like:
<Files xmlrpc.php>     Order Deny,Allow     Deny from all </Files>

After enabling the configuration, it’s crucial to reload Apache to apply the changes:

sudo service apache2 reload

If this step was missed, the rule wouldn’t take effect.

From your logs, it looks like you’re still getting 200 (OK) and 301 (Moved Permanently) responses for some requests to xmlrpc.php, which means the block isn’t being applied correctly. You should see 403 Forbidden instead if the configuration is working.

Regards

You can also install the iQ Block Country plugin. This allows you to deny requests to xmlrpc.php but also to your entire backend. You can allow only your own country for instance. Or block all countries and only allow your own ip address(es).

You can also block countries from visiting your frontend. So if you need some kind of geo fencing around your content you can do this. Or perhaps you just get a lot of spammy comments on your blogs from certain countries then you can block these as well.

alexdo
Site Moderator
Site Moderator badge
November 28, 2024

Thanks for sharing this! I’ve not used this plugin but I’ll definitely have it in mind and will check it out

Regards

I have followed the step 3 and I still having the same issue :S. I have the problem as I can see in my log file, and also everytime I restart the server the website works for some seconds but back the message “Error establishing a database connection”. Any idea what is going on with this?

i follow the step 3 but i have to restart the mysql too…

sudo service mysql restart

this problem have been solved to me…

An easy temporary fix is to IP ban all the offenders.

First get their IPs:

 fgrep '"POST /xmlrpc.php HTTP/1.0" 200 791 "-" "Mozilla/4.0 (compatible: MSIE 7.0; Windows NT 6.0)"' /var/log/apache2/access.log | cut -d' ' -f1 | sort | uniq

159.122.224.173 185.103.252.170 185.130.4.120 185.130.4.197 185.82.202.52 5.196.199.230

Then ban them:

iptables -I INPUT -s 159.122.224.173 -j DROP

etc

alexdo
Site Moderator
Site Moderator badge
November 28, 2024

Heya,

Thanks for sharing this! Your approach is straightforward, but keep in mind a few points to maximize its effectiveness and maintain server health:

To target offenders accurately, adjust your log query to include only high-frequency attackers. For example:

awk '{print $1}' /var/log/apache2/access.log | grep "POST /xmlrpc.php" | sort | uniq -c | sort -nr

This will list IPs by the number of requests, helping you identify the most aggressive offenders.

Use iptables for each IP:

iptables -I INPUT -s <IP> -j DROP

If attacks are frequent, consider automating IP blocking with a tool like Fail2Ban, which can monitor logs and block abusive IPs dynamically.

Regards

Method 3 worked great for me, thanks! I am not too linux savvy but the one additional step I had to do to get it to work was restart MySQL altogether…“service mysql stop” then “service mysql start”.

Thank god for this tutorial, I was losing a bunch of money with my web site down.

alexdo
Site Moderator
Site Moderator badge
November 28, 2024

Hey, I’m glad to hear that you’ve sorted this out!

If you continue facing issues or want to bolster your site’s security further, consider:

  • Using a WordPress security plugin like Wordfence or iThemes Security.
  • Setting up rate limiting or access controls for specific endpoints like /xmlrpc.php.
  • Regularly updating your WordPress installation, plugins, and themes.

Regards

hi dear i can’t access my droplet it shows as power on but in ping status of server ip address giving request time out :( please help me to how to fix it as soon as possible :(

alexdo
Site Moderator
Site Moderator badge
November 28, 2024

Heya,

You can use our recovery console to check on the droplet and regain access.

https://docs.digitalocean.com/products/droplets/how-to/recovery/recovery-console/

Regards

Try DigitalOcean for free

Click below to sign up and get $200 of credit to try our products over 60 days!

Sign up

Join the Tech Talk
Success! Thank you! Please check your email for further details.

Please complete your information!

Become a contributor for community

Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.

DigitalOcean Documentation

Full documentation for every DigitalOcean product.

Resources for startups and SMBs

The Wave has everything you need to know about building a business, from raising funding to marketing your product.

Get our newsletter

Stay up to date by signing up for DigitalOcean’s Infrastructure as a Newsletter.

New accounts only. By submitting your email you agree to our Privacy Policy

The developer cloud

Scale up as you grow — whether you're running one virtual machine or ten thousand.

Get started for free

Sign up and get $200 in credit for your first 60 days with DigitalOcean.*

*This promotional offer applies to new accounts only.