How to Verify mod_security is Actively Blocking Attacks (Not Just Detecting) with Test Cases


10 views

When ModSecurity appears to log attacks but not block them, we need to systematically verify its operational state. First check your configuration:


# Check if SecRuleEngine is On (not DetectionOnly)
SecRuleEngine On

# Verify the default action chain
SecDefaultAction "phase:2,deny,status:403,log,auditlog"

These test payloads should trigger immediate 403 responses when ModSecurity is properly configured:


# SQL Injection test (URL parameter)
curl -I "http://yoursite.com/search?q=1'+UNION+SELECT+password+FROM+users--"

# XSS test (form input)
curl -X POST -d "comment=<script>alert(1)</script>" http://yoursite.com/feedback

# Path traversal test
curl -I "http://yoursite.com/../../etc/passwd"

A proper ModSecurity block should return:

  • HTTP 403 status code (not 404)
  • ModSecurity-specific error message
  • Corresponding audit log entry

If tests aren't blocking:


# 1. Verify rule processing order
grep -R "SecRule" /etc/modsecurity/

# 2. Check rule exclusion lists
cat /etc/modsecurity/crs/crs-setup.conf | grep "SecAction"

# 3. Test with OWASP CRS paranoia level 4
SecAction \
 "id:900000,\
  phase:1,\
  nolog,\
  pass,\
  t:none,\
  setvar:tx.paranoia_level=4"

Create a custom test rule for positive confirmation:


SecRule ARGS:testparam "@contains modsec_test" \
 "id:999999,\
  phase:2,\
  deny,\
  log,\
  msg:'ModSecurity test rule triggered',\
  tag:'application-multi',\
  tag:'language-multi',\
  tag:'platform-multi',\
  tag:'attack-generic'"

Then test with: curl "http://yoursite.com/?testparam=modsec_test"


Many developers face this exact scenario after setting up ModSecurity - they see detection logs but can't confirm actual blocking functionality. The key indicators you should look for:

  • 403 Forbidden responses instead of 404 pages
  • Distinct ModSecurity error pages (when configured)
  • Corresponding entries in audit logs showing "block" actions

Try these simple test vectors that should trigger ModSecurity's default rules:

# SQL Injection test
curl -v "http://yoursite.com/?param=1'%20OR%20'1'%20=%20'1"

# XSS test
curl -v "http://yoursite.com/?param=<script>alert(1)</script>"

# Path traversal test
curl -v "http://yoursite.com/../../etc/passwd"

Ensure your configuration has these critical settings:

# In modsecurity.conf
SecRuleEngine On
SecDefaultAction "phase:2,deny,status:403"
SecAuditEngine RelevantOnly
SecAuditLog /var/log/modsec_audit.log

Add this custom rule to force a block for testing:

SecRule ARGS:testparam "@contains testblock" \
    "id:999999,\
    phase:2,\
    deny,\
    status:403,\
    msg:'Test block triggered',\
    logdata:'Matched %{MATCHED_VAR}'"

Then test with:

curl -v "http://yoursite.com/?testparam=testblock"

When properly configured, your audit log should show entries like:

[timestamp] [unique_id] [client_ip] [block_action] [rule_id] [message]
[timestamp] [unique_id] [client_ip] [block_action] [rule_id] [message]
  • Rule engine set to DetectionOnly mode
  • Incorrect SecDefaultAction configuration
  • Missing or misconfigured audit log settings
  • Rules not properly loaded (check error logs)

For comprehensive testing, consider using the OWASP Core Rule Set (CRS) test cases:

git clone https://github.com/coreruleset/coreruleset
cd coreruleset/tests/regression/tests
./run-regression-tests.sh -h yoursite.com