Debugging
- Going to use the following expression to filter out the logs while checking on the app behavior
tail -f /var/log/apache2/modsec_audit.log | grep -iE ".*notice.*|*.warning.*|.*error.*|.*critical.*"
Problem 1
Message: Rule 7faba9cd8db8 [id "951250"][file "/etc/crs4/rules/RESPONSE-951-DATA-LEAKAGES-SQL.conf"][line "365"] - Execution error - PCRE limits exceeded (-47): (null).
- Don't have any recommendations other than trial end error here. I suggest doing the following (dont forget to restart Apache after making the changes)
nano -w /etc/modsecurity/modsecurity.conf
# PCRE Tuning
# We want to avoid a potential RegEx DoS condition
#
SecPcreMatchLimit 500000
SecPcreMatchLimitRecursion 250000
Problem 2
Message: Warning. Match of "within %{tx.allowed_request_content_type}" against "TX:content_type" required. [file "/etc/crs4/rules/REQUEST-920-PROTOCOL-ENFORCEMENT.conf"] [line "1012"] [id "920420"] [msg "Request content type is not allowed by policy"] [data "|multipart/form-data|"] [severity "CRITICAL"] [ver "OWASP_CRS/4.10.0"] [tag "application-multi"] [tag "language-multi"] [tag "platform-multi"] [tag "attack-protocol"] [tag "paranoia-level/1"] [tag "OWASP_CRS"] [tag "capec/1000/255/153"] [tag "PCI/12.1"]
- As it turns out we are missing Content Type = multipart/form-data. Fixing
nano -w /etc/crs4/crs-setup.conf
SecAction \
"id:900220,\
phase:1,\
pass,\
t:none,\
nolog,\
tag:'OWASP_CRS',\
ver:'OWASP_CRS/4.10.0',\
setvar:'tx.allowed_request_content_type=|application/x-www-form-urlencoded| |multipart/form-data| |text/html|'"
Problem 3 - Fundamental
Message: Warning. Matched phrase "var/log" at ARGS:html. [file "/etc/crs4/rules/REQUEST-930-APPLICATION-ATTACK-LFI.conf"] [line "116"] [id "930120"] [msg "OS File Access Attempt"] [data "Matched Data: var/log found within ARGS:html: ***** tail -f /var/log/apache2/modsec_audit.log
- The problem here is specific page content (shell commands mostly) which is getting picked up when I publish the page. So what do we do ? Two options - signature bypass (which is less than ideal) or a more elegant solution
Bypass example
SecRule ARGS:html "@rx (.*)" \
"id:001001002,\
phase:1,\
pass,\
nolog,\
msg:'Matched pattern bypass',\
ctl:ruleRemoveById=930120"
And now to a more elegant solution. If you stop and think for a second, you'd realize that all these anomalies are getting picked up only when the content is getting pushed into the database. So what can we do ? - We can define a trusted source list allowed to interact with the CMS bypassing the engine. Like this
SecRule REMOTE_ADDR "@ipMatchFromFile admin_panel_whitelist.txt" \
"id:001001001,\
phase:1,\
pass,\
log,\
msg:'Admin Panel WAF bypass - POST|PUT only',\
ctl:ruleEngine=Off,\
chain"
SecRule REQUEST_METHOD "@rx (POST|PUT)"
- Once again checking the logs for false positives and enforcing the blocking threshold
nano -w /etc/crs4/crs-setup.conf
SecAction \
"id:900110,\
phase:1,\
pass,\
t:none,\
nolog,\
tag:'OWASP_CRS',\
ver:'OWASP_CRS/4.10.0',\
setvar:tx.inbound_anomaly_score_threshold=5,\
setvar:tx.outbound_anomaly_score_threshold=4"
- Checking the logs
Action: Intercepted (phase 2)
Apache-Handler: application/x-httpd-php
Stopwatch: 1737805433007092 8481 (- - -)
Stopwatch2: 1737805433007092 8481; combined=5102, p1=911, p2=2835, p3=0, p4=0, p5=1355, sr=75, sw=1, l=0, gc=0
Response-Body-Transformed: Dechunked
Producer: ModSecurity for Apache/2.9.7 (http://www.modsecurity.org/); OWASP_CRS/4.10.0.
Server: Apache
Engine-Mode: "ENABLED"
- If you happened to have Fail2Ban, can have a look there as well
fail2ban-client status apache-modsecurity
Status for the jail: apache-modsecurity
|- Filter
| |- Currently failed: 0
| |- Total failed: 14
| `- File list: /var/log/apache2/error.log
`- Actions
|- Currently banned: 1
|- Total banned: 6
`- Banned IP list: 193.41.206.98