An insignificant WordPress brute-force attack

Earlier this week I noticed a minor brute-force attack against our managed WordPress hosting. The attack lasted for 72 hours and deployed around 2000 unique bots. The botnet attempted on average 100 logins per hour while rotating bots to avoid triggering our automatic defense systems.

The only reason the botnet got flagged was that of repeated login failures from a specific user-agent:

176.59.41.192 - - [23/Jan/2019:03:16:41 +0100] "POST /wp-login.php HTTP/1.1" 403 1397 "http://domain.tld/wp-login.php" "Mozilla/5.0 (Windows NT 6.0; rv:34.0) Gecko/20100101 Firefox/34.0"
88.204.209.77 - - [23/Jan/2019:03:17:27 +0100] "POST /wp-login.php HTTP/1.1" 403 2936 "http://domain.tld/wp-login.php" "Mozilla/5.0 (Windows NT 6.0; rv:34.0) Gecko/20100101 Firefox/34.0"
93.177.15.135 - - [23/Jan/2019:03:18:33 +0100] "POST /wp-login.php HTTP/1.1" 403 2936 "http://domain.tld/wp-login.php" "Mozilla/5.0 (Windows NT 6.0; rv:34.0) Gecko/20100101 Firefox/34.0"
185.13.112.90 - - [23/Jan/2019:03:18:58 +0100] "POST /wp-login.php HTTP/1.1" 403 2936 "http://domain.tld/wp-login.php" "Mozilla/5.0 (Windows NT 6.0; rv:34.0) Gecko/20100101 Firefox/34.0"
194.9.224.232 - - [23/Jan/2019:03:19:38 +0100] "POST /wp-login.php HTTP/1.1" 403 2936 "http://domain.tld/wp-login.php" "Mozilla/5.0 (Windows NT 6.0; rv:34.0) Gecko/20100101 Firefox/34.0"

I can’t imagine the logic behind having the bots identifying themselves with an old Firefox user-agent string (Firefox/34.0), as it’s highly unlikely that legitimate users would be using Firefox 34.0 in 2019. Anyhow, I’m not complaining as a common denominator makes it that much easier to block this kind of undesired traffic.

Blocking access to wp-login.php

By using Apache’s mod_rewrite module, we can restrict POST access to wp-login.php by filtering behavior not observed by legitimate users:

  • Missing or providing the wrong HTTP_REFERER
  • Not proving a HTTP_USER_AGENT string
  • Providing a HTTP_USER_AGENT string commonly used by bots

With that in mind, the following conditions will block POST requests to wp-login.php and thus thwart login attempts from common bots. Make sure to replace the domain\.tld part with the actual domain name or nobody will be able to log in ;-)

<IfModule mod_rewrite.c>
  RewriteEngine On
  RewriteCond %{REQUEST_METHOD} POST
  RewriteCond %{REQUEST_URI} wp-login\.php
  RewriteCond %{HTTP_REFERER} !(.*)domain\.tld(.*) [OR]
  RewriteCond %{HTTP_USER_AGENT} ^-?$ [OR]
  RewriteCond %{HTTP_USER_AGENT} ^.*(firefox\/34.0|firefox\/40.1).* [NC]
  RewriteRule ^(.*)$ - [L,R=403]
</IfModule>

About that Firefox/40.1 user-agent string. Read an older similar tale of another botnet still at large here.

The Moscow connection

I always find it interesting to see where the attacks are originating from geographically. This time around, 80% of the attacks originated from Russia. Moscow alone was responsible for almost 15% of the traffic. Closely following Moscow was Saint Petersburg, Krasnodar, Sverdlovsk, and Rostov making up our top five “attacking” cities.

Top five attacking countries

A simple table listing the top five countries involved in the botnet.

I did not spend much time trying to identify the compromised devices this botnet had drafted, but it seems to be a little of everything. In addition to MikroTik routers of course. If anybody is interested, the list of IP addresses is available from this repository.

Amusingly, I later discovered that I had previously blocked the Firefox/34.0 user-agent on a managed WordPress server so this botnet has probably been around for some time.