Stop Hack Attempts on WordPress xmlrpc.php

I recently noticed a lot of requests to this and other WordPress sites’ xmlrpc.php file. By “a lot”, I mean about 10-20 every second. It wasn’t particularly breaking anything (there aren’t any currently vulnerabilities there that I’m aware of), but it was increasing the load on my server.

My first step was to set an .htaccess rule to give a 403 response. That at least avoided hitting PHP with all those requests. But Apache still had to process them, so I wanted to take it a step further. I’m already using fail2ban, so I wanted to figure out how to stop these requests at that level instead of waiting until they reach Apache.

First, I needed to create a filter, telling fail2ban what kinds of requests I wanted to block. On my system (Ubuntu), I created a file at /etc/fail2ban/filter.d/apache-xmlrpc.conf. The file is fairly simple:

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

This tells fail2ban how to parse the log files to find requests for xmlrpc.php, and where to find the IP address. You might need to adjust the regex if your log files are formatted differently.

Now that we’ve created the filter, we tell fail2ban to use it. We open /etc/fail2ban/jail.conf and add this rule:

[apache-xmlrpc]

enabled  = true
port     = http,https
filter   = apache-xmlrpc
logpath  = /srv/www/*/logs/access.log
maxretry = 6

Adjust the logpath parameter to point to your Apache access logs, and adjust maxretry to taste.

Restart fail2ban:

sudo service fail2ban restart

And you should soon find Apache handling far fewer requests. An added benefit to using fail2ban: legitimate requests to xmlrpc.php (e.g., trackbacks) should still get through.

Update (2013-08-28): This is, of course, a rough first step, and serves me well on my fairly low traffic server. If you’re looking for something more robust, definitely check out Todd’s comment below and read his blog post about protecting your WordPress server.

15 thoughts on “Stop Hack Attempts on WordPress xmlrpc.php”

  1. I think you are the only person I’ve seen who has addressed this specific issue. I’ve had a specific domain of mine on my VPS disabled by my host because the loads on XML-RPC are off the charts. I thought it was a plugin, but no disabling was able to stop it. I finally found your post and added the offending IP ranges to my iptables list, then installed fail2ban. Thanks for the lead!

  2. Thanks for this write up. Strangely enough, whenever I run fail2ban with these added settings my CPU usage for fail2ban-server jumps immediately to 100%. Not sure why, but simply making the filter active=false returns the state to normal.

    I am monitoring about 7 log files, but traffic is pretty light so they aren’t changing a lot. This is on an up-to-date Ubuntu precise (12.04.2 LTS).

    Thanks again.

  3. thanks for putting this up, I have it on my mediatemple DV server but I’m not sure if it is working with the modified regex for the log files

    is there a way to check that fail2ban is preventing the POST to xmlrpc.php ?

    1. Your fail2ban log should indicate which rules are being matched. For example, in my /var/log/fail2ban.log, I see:

      2013-08-17 02:41:24,501 fail2ban.actions: WARNING [apache-xmlrpc] Ban XXX.XXX.XXX.XXX
      
  4. Hi,

    I had similar problems this morning, with a clutch of sites being hammered on xmlrpc.php from several different IP addresses.

    fail2ban is a great solution, but it wasn’t straightforward getting it to work in my environment (Centos 6 + cPanel)

    First, I had to download the source tarball, decompress and then run $python setup.py install (for some reason the yum install version wouldn’t start).

    Second when I started fail2ban (which i did via the client, ie: $fail2ban-client start), it warned me that the filter [apache-xmlrpc] had no actions.

    That didn’t look right, so I added an action to add rule to iptables to block the offending ip, and send me an email. Now this works like a dream.

    So the final config in jail.conf looks something like this:

    [apache-xmlrpc]

    enabled = true
    port = http,https
    filter = apache-xmlrpc
    action = iptables[name=apache-xmlrpc, port=http, protocol=tcp]
    sendmail-whois[name=SSH, [email protected], [email protected]]
    logpath = /home/*/access-logs/*
    maxretry = 4

    Note the very wildcarded log path – if you have a standard install of cPanel then you will need something like this too.
    I have 50+ accounts hosted on my server, and it takes fail2ban a few minutes to parse all the log files when it starts up – you will see pretty much 100% processor usage while it does that. But it soon settles down and behaves itself.

    TODO: I need to get fail2ban running as a service and set it to start on boot. Also the sharpeyed amonst you will note that I should probably filter out ftp or other service logs, as I’m uneccessarily parsing them with this regex.
    Finally, I haven’t added a rule to block https, simply because I don’t host any wordpress blogs over SSL at the present time, so this isn’t an issue for me.

    One final observation is that editing the .htaccess files to block xmlrpc.php with a 403 response was disastrous for me. The DDOS attempts continued at full force and the load just transferred from the php processor to apache, increasing, not decreasing the load. So I don’t recommend this option!

  5. A further update – I’ve noticed that fail2ban is only banning IPs when it starts up – not all the time. Not sure why, wonder if you’ve noticed the same or not? Maybe I have something wrong in the config somewhere . . .

  6. Simon and Rob,

    Although the intention is good here there is something that should be watched with this implementation and a couple of you have touched on those issues.

    The foremost issue is scanning the access.log which can be a bad thing. Depending on the traffic that the site gets this can become VERY CPU intensive and is not recommended. If you’re a hosting provider this is even more so not recommended. When the issue with the massive attacks on WP sites arose (April-June 2013) all major hosting providers, including us (small guys) immediately blocked all access to wp-login.php and I’m talking Go-Daddy, LiquidWeb, etc. This blocked access for legitimate purposes as well but it kept the servers up. Once things calmed down and like minds met we implemented more robust procedures.

    During a SYN Flood Attack for example your access log will quickly increase in size. The combination of the attack plus Fail2Ban scanning it can cause issues. In addition, Fail2Ban DOES scan logrotated files. Therefore, if you have had this server for a while and have a lot of rotated files it can make things worse.

    The “more” correct way to deal with this would be to hook into the WP login process (wp_authenticate) and write to a custom error log specifically designed for WordPress. Setup your Fail2Ban filters and only scan that log.

    When you say that Fail2Ban is not picking them up all the time are you referring to immediately after you attempt an invalid login? Fail2Ban can sometimes take a bit before it reads the entire log file. Do you have your IP whitelisted?

    We have a lot of information on Fail2Ban and detailed implementations for WordPress documented. If anyone would care to take a look here’s the link

    1. Thanks for the helpful info, Todd. The performance concerns don’t particularly impact this humble site, but that’s very good to know when trying to apply this on a larger scale. I’ve updated the post above with a link.

  7. I know this is an old post but I’m experiencing this issue. Thank you for posting this solution.

    I’m curious why the original config does not include an “action” directive. I implemented this without it and was getting bans in my logs, but iptables was not being modified. Then I saw Simon’s post. I’m also running CentOS, and am wondering if the Debian package has some default for iptables action. Any ideas?

    Drew

  8. Hy, can anyone help me stop the xmlrpc attacks ? the hostserver are keep telling me that i’am xmlrpc vulnerable, and they vps server is ok! i stopped the xmlrpc for the moment with a plugin!

  9. In case you are not aware (sorry if you already know this), but XMLPRC is used for posting content remotely. The xmlrpc.php file is what WordPress uses to allow you to post remotely.

    As you know, one of the things we all love about WordPress is how easy it is to create new websites and to manage the content. These are the very same reasons why hackers also love WordPress.

    If you are not posting comments to your website remotely, one of the quickest way to get yourself out of this situation is to rename the xmlrpc.php file to some fictitious name. Make sure you change the file type to anything other than “.php.” This way, you will remove the possibility that the server may accidentally run the code.

    If you are doing posts remotely, here’s some code you can add to your .htaccess file:

    order deny,allow
    deny from all
    allow from 123.456.789.123 allow {where “123.456.789.123” is the IP address of the computer that can use xmlrpc.pgp}

    WordPress has a bunch of security holes and we have been victimized many times. I a solution that so far has helped me secure our sites more than anything else we have tried.

    Here is the link ==> http://jvz8.com/c/9278/20094

    Hopefully, WordPress will not open up new holes with the next WP update.

    1. the xmlrpc file, is not used by wordpress also for the jetpack plugin ?? if i delete de xmlrpc file, the jetpack it wil be working ???

      Thank you

Comments are closed.