WordPress Login Protection with ModSecurity

No ModSec? Check out WordPress Login Protection With .htaccess

LockIf you’re on Liquid Web servers, this was already done for you. If you’re not, you should still be able to use this code on your own ModSecurity instance. Since this is a way better method to block people than via a plugin, in my opinion, I thought it would be a good idea to share it here. With this rule, you won’t have quite as many http requests.

WordPress is a popular publishing platform which is known for its robust features, numerous templates, and large support community. Unfortunately, due to such popularity, WordPress is also constantly subject to attempts at exploiting vulnerabilities. Ensuring WordPress and any associated plugins are installed with the most current versions is an important means of securing your site. However, ModSecurity provides a significant amount of further security by providing an application firewall.

ModSecurity (also known as “modsec”) has proven itself useful in a variety of situations, and again this is true in assisting with WordPress brute force attempts resulting in a Denial of Service (DoS) attack. While a number of WordPress plugins exist to prevent such attacks, custom modsec rules can prevent such attacks for all WordPress installations on a server. Modsec immediately filters incoming HTTP requests, which assists against taxing server resources.

These rules will block access for the offending IP address for 5 minutes upon 10 failed login attempts over a 3 minute duration. These rules have been automatically updated in the custom rules for Liquid Web’s ServerSecure service. For customers without ServerSecure, these rules can be added to their custom modsec rules. To accomplish this, edit your custom modsec user rules and append the file with the rules provided below. For CPanel servers, this file is likely located at /usr/local/apache/conf/

SecAction phase:1,nolog,pass,initcol:ip=%{REMOTE_ADDR},initcol:user=%{REMOTE_ADDR},id:5000134
<Locationmatch "/wp-login.php">
    # Setup brute force detection.

    # React if block flag has been set.
    SecRule user:bf_block "@gt 0" "deny,status:401,log,id:5000135,msg:'ip address blocked for 5 minutes, more than 10 login attempts in 3 minutes.'"

    # Setup Tracking.  On a successful login, a 302 redirect is performed, a 200 indicates login failed.
    SecRule RESPONSE_STATUS "^302" "phase:5,t:none,nolog,pass,setvar:ip.bf_counter=0,id:5000136"
    SecRule RESPONSE_STATUS "^200" "phase:5,chain,t:none,nolog,pass,setvar:ip.bf_counter=+1,deprecatevar:ip.bf_counter=1/180,id:5000137"
    SecRule ip:bf_counter "@gt 10" "t:none,setvar:user.bf_block=1,expirevar:user.bf_block=300,setvar:ip.bf_counter=0"

Source: Liquidweb and Frameloss and MNX Solutions

Logically, someone can extend this code to any file, like bb-login.php or Special:UserLogin, depending on where they’re being hacked.

ETA: Rarst asked if I’d have to use wildcards with Locationmatch since WP is often in a subfolder. I read the Apache doc on locationmatch and it says that it’s using regex, so it should just look for ‘/wp-login.php’ in the URL. If I wanted to only look for example.com/wp-login.php then I’d use ^wp-login.php instead. If I got that wrong, please let me know!


29 responses to “WordPress Login Protection with ModSecurity”

  1. Rarst asked if I’d have to use wildcards with Locationmatch since WP is often in a subfolder. I read the Apache doc on locationmatch and it says that it’s using regex, so it should just look for /wp-login.php in the URL. If I wanted to only look for example.com/wp-login.php then I’d use ^wp-login.php instead. If I got that wrong, please let me know!

  2. Notes people insist on tweeting me, rather than leaving comments (seriously?)

    1) Yes it works in subdirectories
    2) As of ModSec 2.7.3, you can use htaccess overrides again, but I doubt everyone’s on it
    3) Original original source was frameloss – http://www.frameloss.org/2011/07/29/stopping-brute-force-logins-against-wordpress/

    By the way, if you leave a comment, you’re actually MORE likely to get a reply. Also it helps anyone who google’s and finds this page. Twitter is transient, folks 😉

  3. Very cool.

    I’ve been trying to get the nginx version mod_security up and running on my nginx VPS playground for a while (unsuccessfully but I’m not very dedicated). I’m going to check if it includes brute force protection like this and if not try to get it added.

    Thanks for the idea.

    PS. I’m utterly perplexed by your new avatar, “the hat” is so ingrained in my head…

    1. The hat would hide my blue hair 😉 Pretend its an invisible fedora.

      I would assume that mod security would always work the same way, so the brute force rules should be applicable be it apache or nginx, otherwise what the hell is the point of it?

  4. Some of my sites are getting slammed by login attempts so I’m thinking of using ModSecurity. But I don’t understand the official installation instructions. They’re not basic enough for me. Do you have any suggestions for instructions for people who are clueless?

    For example these instructions:

    Edit Makefile.win to configure the Apache base and library paths. Compile with: nmake -f Makefile.win Install the ModSecurity module with: nmake -f Makefile.win install

    What does “Compile” mean?

    I’m running Windows 7 64-bit.

    1. I installed mine with Apache (and that’s pretty common). Are you sure you don’t already have it installed? You can run this command to check : grep "modsecurity" /usr/local/apache/logs/error_log

      That gave me this:

      [Thu Apr 04 09:10:23 2013] [notice] ModSecurity for Apache/2.7.2 (http://www.modsecurity.org/) configured.

      What server OS are you on?

    2. My millermosaicllc.com site is not the one that’s getting hammered.

      Where do I “run this command”?

    3. It turns out those sites are running ModSecurity but since it’s shared I can’t make changes. Those sites are on inmotion hosting and I’m not the only customer getting slammed. They said they’re working on solutions from their end so I pointed the guy on the phone to this post. Here’s hoping they use this.

    4. You run the command via shell (so you SSH in and type that)

      Yeah, if you don’t have VPS/Dedicated access to a server, there’s very little you can use unless you’re on ModSecurity 2.7.3. If you ARE you can use this in your .htaccess file instead, though I’m not 100% sure of the formatting.

  5. On Apache/Linux servers, we’ve found that once the modsec rule is in place, you can alleviate additional load by adding this to your sites .htaccess file:

    ErrorDocument 401 default

    This stops WP from trying to process any 404’s for 401.shtml, and results in a flat text file being served with no redirects being processed while modsec is blocking the IP.

    Additionally on Linux servers, using configserver firewall (CSF) with LF_MODSEC enabled will ban IP’s in iptables if they continue abuse once modsec has blocked them.

    1. I should note that I have CSF, and I enabled LF_MODSEC (mine is set to 5 attempts before you’re shitcanned).

  6. I’d love a bit of help getting this configured on my server. I have a Mod Security area on my WHM panel. I tried cutting and pasting that info above into the config area. Tried locking myself out, but didn’t have any luck. But there is now some entries showing up that look like this…

    Unable to store collection (name “ip”, key “”). Use SecDataDir to define data directory first.

    And the action related to it was 200 — which makes me think I was close.

    1. What’s SecDataDir set to in your conf? 🙂 In modsec2.user.conf I see mine is this:

      SecDataDir /tmp

  7. The only thing in there is what I put above. Should I place that before the code above?

    1. If that’s the ONLY thing, you may be editing the wrong files…What file are you editing, just to be 100% sure?

  8. I’m attempting to do it via WHM. But I googled the file you said above and found it, and the only thing inside the file is what I placed in the WHM… which is what I cut and pasted from above. Is there another file I should be placing it in?

    1. It really depends on your server. My file is FILLED with stuff, see, and … Huh (Oh you CAN edit it in WHM! Hah, I was still using command line).

      Okay, put this at the top:

      SecUploadDir /tmp
      SecTmpDir /tmp
      SecDataDir /tmp

      SecRequestBodyAccess On

  9. Looks like it is working. After 10 unsuccessful logins it started giving me an error of some sort about too many redirects. Thank you!

    1. Yay! You may also want to create a real 401.html file, and redirect to it in .htaccess:

      ErrorDocument 401 /401.html

      That will help keep the load off WP. (I had done this for other reason, but my friend B suggested it.)

  10. VPS are mostly targeted by hackers. thanks for the wonderful tutorial to have some security fix than being none.


    1. Hackers, maybe. But this sort of scripted attack isn’t looking for VPS or Dedicated or Slice or whatever. It’s looking for WordPress. A hacker is looking for ME. A cracker, or a script kiddie, is looking for destruction.

      I’d put money down that this is a plot to infect our servers and then use them for zombie attacks. Probably DDoS. If I didn’t know better, I’d say it was anon, but this isn’t their style.

  11. […] tường lửa web của CloudFlare để chống tấn công “brute-force“ hoặc thiết lập bảo mật cho phần mod security trên máy chủ […]

  12. […] most prevalent technical solution is using ModSecurity rules on Apache to limit the login attempts. Of course, this requires that your server is running Apache and has ModSecurity available or you […]

  13. […] this is a good post on setting up mod_security for apache:https://halfelf.org/2013/wp-login-protection-modsec/   Source material for above article   […]

  14. […] most prevalent technical solution is using ModSecurity rules on Apache to limit the login attempts. Of course, this requires that your server is running Apache and has ModSecurity available or you […]

  15. Thanks so much, I have installed this on my cpanel/WHM/configserver VPS, and it works like a dream. Now invalid logins are being blocked after 10 attempts, and the IP blocked for 5 minutes. Perfect.

  16. Hi Mika,

    For Nginx users there is an alternative to mod_sec:

    In your main nginx.conf add to the http{} area:
    limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;

    Then edit your vhost file, or if one big nginx.conf file inside the server area:

    location ~ \.php$ {
    limit_req zone=one burst=5 nodelay;

    1. Does that hook into ip blocks though? The bonus of Mod Sec is that it stops the IP from making more attacks. Otherwise this is just another htaccess/nginx rule. That’s not a bad thing, it’s just not quite why I love mod sec 🙂 And hate it. We have a love/hate thing.

  17. […] solution that almost everyone will recommend is to use ModSecurity rules on Apache to limit the login attempts. However, in order to use this solution you have to be using Apache in the first place. You can […]