As a server admin I am trying to find/create a Mod_Security rule to detect & block multiple login failures on the latest version of Joomla. There's a lot of examples online to prevent brute force attacks (e.g. 5+ requests to the login form) but I haven't found a rule that correctly detects login failures only. The examples I found are also triggered by successful logins.
Some of our hosting clients have many Joomla sites and can legitimately have many logins to Joomla sites within a short time frame, especially when they're working through a list of sites and applying updates. Hence it's really important the rule can tell the difference between successful logins and failed logins.
I found an answer from March 2015 here: mod_security ruleset for Joomla! admin but in my own tests it does not detect login failures. Even with logging enabled it's not detecting anything. I suspect the code is outdated.
I found another ModSec rule published by IT Octopus at A ModSecurity Rule to Block Brute Force Attacks on a Joomla Website | itoctopus The code is below. I tested it on a server but I found it was too sensitive and it blocked me after I logged in + out of Joomla (with correct credentials).
Note: Blocks of code don't seem to be working on cPanel forum today so I've enclosed the code in quotes so I can still share it with you.
It uses ModSecurity phase 5 (analysing the log files) so I'm not sure if this is a disadvantage. And more importantly, in my testing I couldn't get it to work. Even with logging enabled, it didn't detect failed logins and didn't restrict access. Here is the code:
Some of our hosting clients have many Joomla sites and can legitimately have many logins to Joomla sites within a short time frame, especially when they're working through a list of sites and applying updates. Hence it's really important the rule can tell the difference between successful logins and failed logins.
I found an answer from March 2015 here: mod_security ruleset for Joomla! admin but in my own tests it does not detect login failures. Even with logging enabled it's not detecting anything. I suspect the code is outdated.
I found another ModSec rule published by IT Octopus at A ModSecurity Rule to Block Brute Force Attacks on a Joomla Website | itoctopus The code is below. I tested it on a server but I found it was too sensitive and it blocked me after I logged in + out of Joomla (with correct credentials).
Note: Blocks of code don't seem to be working on cPanel forum today so I've enclosed the code in quotes so I can still share it with you.
Next, I found a ModSecurity rule at Brute force protection with ModSecurity » Artefact.io and it's the one I've been using on my servers for many months. It's been working really nicely until yesterday when we found a bug. A client has 10 Joomla websites and they found when they logged into them (with correct credentials) it resulted in their IP being restricted. I was able to replicate this during my own testing. Therefore the code below is the best code we've found yet but the com_login / login lines don't seem to distinguish between login failures and successful logins. It works to prevent general brute force but it doesn't work when a client has many Joomla sites and is legitimately accessing multiple installs at once. This is the code:<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 ARGSption "@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"
</Location>
Finally, I read some posts that suggested "the P3P header is returned after a successful login" and this could be used in a ModSecurity rule. It was suggested by @godzillante here: mod_security ruleset for Joomla! admin# Joomla Brute Force
SecAction "phase:1,pass,setvar:TX.max_requests=6,setvar:TX.requests_ttl=180,setvar:TX.block_ttl=900,initcol:ip=%{REMOTE_ADDR},nolog,id:5001000"
<LocationMatch "/administrator/index.php">
SecAction "phase:2,chain,nolog,id:5001022"
SecRule REQUEST_METHOD "^POST$" "chain"
SecRule ARGS_POST_NAMES "^username$" "chain"
SecRule ARGS_POST_NAMES "^passwd$" "chain"
SecRule ARGS_POSTption "^com_login$" "chain"
SecRule ARGS_POST:task "^login$" "chain"
SecAction "setvar:ip.request_count=+1,expirevar:ip.request_count=%{TX.requests_ttl}"
SecRule IP:request_count "@ge %{TX.max_requests}" "phase:2,drop,setvar:ip.blocked=1,expirevar:ip.blocked=%{TX.block_ttl},log,msg:'Joomla brute force. Blocking for %{TX.block_ttl} seconds',id:5001023"
</LocationMatch>
It uses ModSecurity phase 5 (analysing the log files) so I'm not sure if this is a disadvantage. And more importantly, in my testing I couldn't get it to work. Even with logging enabled, it didn't detect failed logins and didn't restrict access. Here is the code:
My objective here is to improve the code "# Joomla Brute Force" (above) because it does block brute force flooding but unfortunately it also blocks users when they are legitimately logging into Joomla a lot. I need code that can tell the difference between a login failure and a successful login to Joomla. I've been working on this for some time so I'm reaching out to the community here. Thanks in advance!SecAction phase:1,nolog,pass,initcol:ip=%{REMOTE_ADDR},id:5000144
<Locationmatch "/administrator/index.php">
SecRule ip:bf_block "@gt 0" "deny,status:401,log,id:5000145,msg:'ip address blocked for 5 minutes, more than 5 login attempts in 3 minutes.'"
SecRule RESPONSE_HEADERS:P3P "streq 0" "phase:5,t:none,nolog,pass,setvar:ip.bf_counter=0,id:5000146"
SecRule RESPONSE_HEADERS:P3P "!streq 0" "phase:5,chain,t:none,nolog,pass,setvar:ip.bf_counter=+1,deprecatevar:ip.bf_counter=1/180,id:5000147"
SecRule ip:bf_counter "@gt 5" "t:none,setvar:ip.bf_block=1,expirevar:ip.bf_block=300,setvar:ip.bf_counter=0"
</locationmatch>
Last edited by a moderator: