WordPress brute force attack via wp.getUsersBlogs

Published: 2014-07-22
Last Updated: 2014-07-22 19:35:57 UTC
by Daniel Wesemann (Version: 1)
10 comment(s)

Now that the XMLRPC "pingback" DDoS problem in WordPress is increasingly under control, the crooks now seem to try brute force password guessing attacks via the "wp.getUsersBlogs" method of xmlrpc.php. ISC reader Robert sent in some logs that show a massive distributed (> 3000 source IPs) attempt at guessing passwords on his Wordpress installation. The requests look like the one shown below

and are posted into xmlrpc.php. Unfortunately, the web server responds with a 200-OK in all cases, because the post to xmlrpc.php actually WAS successful. The expected "403 - Not Authorized" error is part of the XML message that the server returns as payload. Hence, to determine what is going on, relying on simple HTTP web server logs is not sufficient. One of the problems with this is that "traditional" means of curbing brute force attacks in WordPress, like using BruteProtect, are less effective, because most of these add-ons tend to watch only wp_login.php and the associated wp_login_failed result, which does not trigger in the case of an xmlrpc login error.

If you are seeing similar attacks, and have found an effective way of thwarting them, please share in the comments below.



10 comment(s)


wp.getUsersBlogs is one of the xmlrpc.php attacks going on lately. On http://www.saotn.org/huge-increase-wordpress-xmlrpc-php-post-requests/ I blogged on this wp.getUsersBlogs but I couldn't log the other type of attack in the wild yet.

At least, I think it's a different attack because the POST payload is 10 times larger in bytes.
Why not use the iptables match feature and combine it with count? You could block IPs based on number of attempts in a given time. I've used that method several times when fighting cachebusting attacks, and it works great.
I simply added a line of regex:

^.*\[.*\] 200 - <HOST> - .* \/xmlrpc\.php.*HTTP.*$

to a fail2ban filter. In my fail2ban jail.local file, that filter is triggered when

maxretry = 2
findtime = 120
bantime = 86400

Easy, and the server is now even more zen-like.

The botnet found my site yesterday (2014 Aug 3) morning. 4100+ individual IPs, and this morning, 24 hours later, it is still going strong.

I did the following:

In Apache, I locked down xmlrpc.php, since it's my own website and I don't use any of the features supported by xmlrpc.

# Restrict access to xml-rpc
<Files xmlrpc.php>
Order Deny,Allow
Deny from all
Allow from xx.xxx.xxx.xx

That causes an authorization error to be logged in Apache's error.log, which then is picked up by the apache-auth fail2ban filter, which is tied to an IPSET line in my firewall, sending a "port unreachable" ICMP.

Finally, I have some custom software that scans Apache's access.log for virulent signatures every hour, and adds those IPs to an IPSET in my firewall. I merely added a signature for POST xmlrpc.php. Packets from these attackers are unceremoniously dropped and are added to a more-or-less permanent blacklist.

So, three layers of protection. Since it's my own private webserver, I can do some things that sysadmins for more public servers can't.
We are having the same issue, after about 3 POST requests a new IP does the same thing. We have had about 3000-4000 IPs and are getting these POST requests to xmlrpc.php at about 1-50 per second on our servers.
Brute force method to block all access to /xmlrpc.php:

iptables -I INPUT -p tcp --dport 80 -m string --string "POST /xmlrpc.php" --algo bm -j REJECT --reject-with tcp-reset

You could also block only requests that include the "<methodName>wp.getUsersBlogs</methodName>" string, just to make sure that you're not blocking legitimate use of /xmlrpc.php if you want.

You can get fancier and use iptables's --recent and blacklisting capabilities, but you don't really want to punish the poor victim of a botnet by blocking all their traffic, do you? That's why we're doing at the iptables level and not the fail2ban level. A legitimate user at the site you just fail2banned may want legitimate information from one of your wordpress sites.
There is a new brute force exploit for xmlrpc.php. Attackers are using XMLRPC API method wp.getUsersBlogs to brute force logins with dictionaries.

I wish I was keen on ModSecurity :(
I've ended up using a combination of a modification to xmlrpc.php and fail2ban to leverage the power of fail2ban to automatically ban these attackers.

The general description is that I'm looking at the XML payload (if one exists) delivered in the post to xmlrpc.php. If I determine to not be a valid post (exercise left to the reader) I utilize syslog() to write a log message alerting of such. Then I have an added jail in fail2ban that looks for these log entries and bans as appropriate.

Should this attack morph into a more sophisticated one I plan on adding further logic to my assessing the XML payload to log successful use of the XML-RPC interface so that excessive posts can also trigger further fail2ban action.

I currently know that the XML-RPC interface supports 30+ actions, so I understand the last paragraph potentially represents a bit of work. But for now it's jailing the attackers.
For those on a Windows server where using .htaccess isn't possible, below is how to disable the two methods that get abused for ping-backs and brute-force attacks.

Add the following code to the top of your Wordpress Theme's functions.php file:

add_filter( 'xmlrpc_methods', 'remove_xmlrpc_pingback_ping' );
function remove_xmlrpc_pingback_ping( $methods ) {
unset( $methods['pingback.ping'] );
return $methods;
} ;

add_filter( 'xmlrpc_methods', 'Remove_Unneeded_XMLRPC' );
function Remove_Unneeded_XMLRPC( $methods ) {
unset( $methods['wp.getUsersBlogs'] );
return $methods;

Diary Archives