In my last post I showed how to use Selenium to make complex brute force attacks easier. I showed a very basic and quick example against my website. Here is an even shorter post on how to mitigate the attack using the mod_security Apache module. I won’t cover how to install it or configure it, but just show the rules I am using to detect and respond to a similar brute force attack. It works reasonably well, although I must admit I haven’t done extensive testing with these rules.
I don’t want to be blocked forever just in case I did something dumb, so I setup the rules to only blacklist a particular IP address for only five minutes. You can definitely play with the timing and number of failed login attempts required to trigger the filter. The way it is setup, it will block an IP address from accessing only the login page (the rest of the site is still available) if that IP address fails 15 times in three minutes. The block lasts for five minutes, and is then reset.
Before showing you the rules a brief explanation is in order. Mod_security allows rules to work off of persistent storage. There are a defined number of collections, and within them you can set a variable and a value. There are a few features that allow you to either deprecate the count of a numeric variable over time, or to expire it completely after a specified timeframe. Unfortunately, these variables work in an unexpected way. I initially setup my rules to set a block variable (IP.bf_blocked) in the IP collection once a certain threshold had been reached, and the variable was set to expire in 5 minutes. Every time I accessed the site after triggering the rule, I was still blocked. I kept asking why aren’t my modsecurity expirevar values being honored? Frustrating!
So after furious searching and trying to figure out what was happening, I finally found a post here that explains the problem . . . “The reason for this is how ModSecurity handles expiry timers for variables. Basically, every time a collection is updated, the LAST_UPDATE_TIME timestamp for that collection gets set to the current time. Since we increment the request_count variable for every request, this will monotonically increase.”
Okay, that makes sense. The examples they provide are pretty good, but there are a couple of errors in the rules that mean they don’t work right. Anyways, based on that information and some testing here is what I came up with for the wordpress login page: Continue reading »
