A ModSecurity Rule to Block Brute Force Attacks on a Joomla Website

At itoctopus, we dedicate a lot of time to research, especially on enhancing Joomla’s security and performance. Today’s post is a fruit of that research, as we have managed to devise a concise ModSecurity rule to block brute force attacks on a Joomla website.

In case you don’t know what ModSecurity is, it is a firewall module that integrates with the Apache web server (among other web servers). What makes it very powerful is its versatility: it has a rules engine which allows system administrators and developers to develop rules to block an IP based on the its activity, and it has some built-in generic rules that can be whitelisted if they cause problems to the hosted application.

Going back to Joomla, most Joomla websites suffer from brute force attacks on the login page of their backend, and, because of that, their administrators resort to some 3rd party extensions that can handle brute force attacks at the application level. The problem with such extensions, however, is the fact that they are extensions, which means the Joomla framework must be loaded everytime the attack takes place.

ModSecurity, on the other hand, blocks brute force attacks at the server level, which means that the offending IP will not even reach the Joomla application, which is much better from server load perspective.

So, how do you block brute force attacks on a Joomla website with ModSecurity?

We’re glad you have finally asked. Here is a step-by-step super-easy to implement instructions on how to do that:

  • ssh to the server as root.
  • Edit the custom.conf file located under the /usr/local/apache/conf/modsec2/ folder (note: this folder location is the one used in a WHM based server, if you’re using something different, then the folder location might be different). You can use vi to edit the file by just issuing this command:

    vi /usr/local/apache/conf/modsec2/custom.conf

  • Add the following code to the custom.conf file:

    <Location /administrator>
        SecDefaultAction phase:2,deny,status:403,log,auditlog
        SecRule IP:bf_counter "@eq 5" "id:1000002,phase:2,log,block,expirevar:IP.bf_counter=3600,msg:'IP address blocked because of a suspected brute force attack on the Joomla website'"
        SecRule ARGS:option "@streq com_login" "id:1000000,phase:2,chain,t:none,log,pass,msg:'Multiple Joomla authentication failures from IP address', setvar:IP.bf_counter=+1"

  • Save the file and then restart Apache using the following command:

    service httpd restart

  • Try to login to the Joomla website 5 times with wrong credentials and, on the sixth time, you will be directed to a 403 Forbidden page.

  • Now go back to sleep knowing that malicious users will not exhaust your server with their incessant brute force attacks!

Now, of course, you might be wondering what that gibberish code that you added to the custom.conf file really means, so let us explain…

This line…

SecDefaultAction phase:2,deny,status:403,log,auditlog

…specifies what action will be taken when the rule blocks the IP. In this line, we are telling ModSecurity to deny access to the page with a 403 error. Not much else you need to know here.

This line…

SecRule IP:bf_counter "@eq 5" "id:1000002,phase:2,log,block,expirevar:IP.bf_counter=3600,msg:'IP address blocked because of a suspected brute force attack on the Joomla website'"

Checks the variable bf_counter if it’s equal to 5. If it is, then the following happens: rule number 1000002 is triggered (you can give the rule any number you want, provided that number is not already assigned to another rule), we log the event (using the log instruction), we block the IP (using the block instruction), we remove the bf_counter variable after 3600 seconds (hence the expirevar:IP.bf_counter=3600 code – which means that the attacker will be blocked from accessing the page for 3600 seconds), and then we specify which message ModSecurity should have in the logs (which is this one “IP address blocked because of suspected brute force attack on the Joomla website”)

This line…

SecRule ARGS:option "@streq com_login" "id:1000000,phase:2,chain,t:none,log,pass,msg:'Multiple Joomla authentication failures from IP address', setvar:IP.bf_counter=+1

…is the heart of the blocking logic and it took us a lot of time just to know what to have in there. You see, when you login unsuccessfully to a Joomla website, com_login will be a post value passed back to the login page. This value is not passed to any page once the login is successful, which means that every time we see com_login in a post value, it means that we have an unsuccessful login, and we must increment the login counter. The line above does that the following way: it checks if any of the ARGS variables (any post or get variable) has com_login in its value (@streq com_login), if it is, then we define rule 1000000, which will increment the bf_counter by 1. The bf_counter variable is checked by the previous rule: once above 5, the request will be blocked.

Can the ModSecurity rule above be modified to be more lenient just so false positives are not blocked immediately for an extended period of time?

Yes! For example, if you want to change the number of retries to 10 and reduce the time that it takes to reset the number of retries to 30 minutes (1800 seconds), then all you need to do is change the second line in the rule (well, technically the third line if you count the <location… line as the first line) to:

SecRule IP:bf_counter "@eq 10" "id:1000002,phase:2,log,block,expirevar:IP.bf_counter=1800,msg:'IP address blocked because of suspected brute force attack on the Joomla website'"

Are there any caveats?

Well, as a matter of fact, there are 2 caveats:

  1. The above rule effectively makes com_login a blacklisted word, which means that if you have an article with com_login anywhere in its body, and you save it, then every save will count towards the bf_block limit. Of course, the absolute majority of Joomla websites will not use the word com_login anywhere in their content, but some technical websites may.
  2. We are not resetting bf_block when the login is successful, which means that if, you try to login 3 times with wrong credentials, and then you login successfully, and then you logout, and then you login 2 times with wrong credentials, then you will be blocked on the 6th attempt.

We hope you enjoyed this post the same way we enjoyed researching it and writing it (note that we used the book ModSecurity Handbook which is written by one of the programmers who heavily worked on ModSecurity). If you need a little help with the implementation, then we can definitely help. Just contact us and we’ll do it for you swiftly, cleanly, and for a very affordable fee!

3 Responses to “A ModSecurity Rule to Block Brute Force Attacks on a Joomla Website”
  1. Comment by Joseph Simony — June 26, 2016 @ 7:48 am

    Thanks for sharing; looks like a great Modsec rule…

    The thing is we’re running several WHM/cPanel based servers and – despite what you wrote – there’s no such folder (modsec2) in any of them although ModSecurity is installed on all of them.

    We have modsec config files under /usr/local/apache/conf. Should the modsec2 folder created manually?

  2. Comment by Fadi — July 5, 2016 @ 11:24 pm

    Hi Joseph,

    Sorry for the late reply. Yes – that folder should be created manually if it’s not there. Please report back and tell us whether this rule worked for you or not!

  3. Comment by John — December 21, 2020 @ 10:58 am

    Thanks for sharing these rules. During my tests, the ModSec rule is not triggered no matter how many times I submit invalid login details to Joomla. I know this rule is a few years old. Should it still work?

Leave a comment