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. Ipstenu (Mika Epstein) Avatar

    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. Ipstenu (Mika Epstein) Avatar

    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. Jon Brown Avatar

    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. Ipstenu (Mika Epstein) Avatar

      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. Yael K. Miller Avatar

    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. Ipstenu (Mika Epstein) Avatar

      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. Yael K. Miller Avatar

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

      Where do I “run this command”?

    3. Yael K. Miller Avatar

      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. Ipstenu (Mika Epstein) Avatar

      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. AlexK Avatar

    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. Ipstenu (Mika Epstein) Avatar

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

  6. Scott Hack Avatar

    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. Ipstenu (Mika Epstein) Avatar

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

      SecDataDir /tmp

  7. Scott Hack Avatar

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

    1. Ipstenu (Mika Epstein) Avatar

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

  8. Scott Hack Avatar

    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. Ipstenu (Mika Epstein) Avatar

      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. Scott Hack Avatar

    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. Ipstenu (Mika Epstein) Avatar

      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. Robin @ dailytut Avatar

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


    1. Ipstenu (Mika Epstein) Avatar

      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. Craig Avatar

    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. Simon Avatar

    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. Ipstenu (Mika Epstein) Avatar

      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 […]

%d bloggers like this: