Brute-Force Authentication Protection with ModSecurity

IP-Based Blocking ----------------- The following ModSecurity script protects from brute-force authentication attacks by blocking IPs. It does this by checking the response code sent by the login page (/sessions). HTTP status 200 means a failed authentication attempt. After 3 attempts the IP is blocked. ```apacheconf # Uncomment to troubleshoot #SecDebugLogLevel 9 #SecDebugLog /tmp/troubleshooting.log # Enforce an existing IP address block SecRule IP:bf_block "@eq 1" \ "phase:2,deny,\ msg:'IP address blocked because of suspected brute-force attack'" # Check that this is a POST SecRule REQUEST_METHOD "@streq POST" "phase:5,chain,t:none,nolog,pass" # AND Check for authentication failure and increment counters # NOTE this is for a Rails application, you probably need to customize this SecRule RESPONSE_STATUS "^200" \ "setvar:IP.bf_counter=+1" # Check for too many failures from a single IP address. Block for 10 minutes. SecRule IP:bf_counter "@ge 3" \ "phase:5,pass,t:none, \ setvar:IP.bf_block,\ setvar:!IP.bf_counter,\ expirevar:IP.bf_block=600" ``` Username-based Blocking ----------------------- A serious hacker will have billions of IPs, yes billions in the near future, so it's better to block by username. To block usernames, use this script: ```apacheconf # Retrieve the username SecAction phase:2,nolog,pass,initcol:USER=%{ARGS.username} # Enforce an existing username block SecRule USER:bf_block "@eq 1" \ "phase:2,deny,\ msg:'Username \"%{ARGS.username}\" blocked because of suspected brute-force attack'" # Check that this is a POST SecRule REQUEST_METHOD "@streq POST" "phase:5,chain,t:none,nolog,pass" # AND Check for authentication failure and increment counters # NOTE this is for a Rails application, you probably need to customize this SecRule RESPONSE_STATUS "^200" \ "setvar:IP.bf_counter=+1" # Check for too many failures for a single username SecRule USER:bf_counter "@ge 3" \ "phase:5,t:none,pass,\ setvar:USER.bf_block,\ setvar:!USER.bf_counter,\ expirevar:USER.bf_block=600" ``` Password-based Blocking ----------------------- Hackers might want to try a reverse brute-force attack on passwords, so you could also block multiple failed login attemps that use the same password. Just modify the script to read the password parameter: ```apacheconf # Retrieve the password parameter SecAction phase:2,nolog,pass,initcol:USER=%{ARGS.password} ``` Note, you might want to use the RESOURCE collection instead of USER, if you're blocking both usernames and passwords. On Learning ModSecurity ----------------------- \* Buy the ModSecurity Handbook \* Use Lua when possible. ModSecurity rules are severely limited by the Apache configuration language. \* Use chain for controlling flow. chain = AND operator. OR operator is |. \* There are 5 collections: GLOBAL, IP, RESOURCE, SESSION, USER. Future versions might give you unlimited collections... \* Use LocationMatch and SecDebugLog when troubleshooting: ```apacheconf SecDebugLogLevel 9 SecDebugLog /tmp/troubleshooting.log ```