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


2 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