wordpressapachewordpress-themingowaspmod-security

ModSecurity breaking the Wordpress Theme editor, cannot write proper exclusion rules


This is about writing proper ModSecurity rules. I hope there is an expert out there who can help me.

I have ModSecurity 2.9.3 and the OWASP CRS 3.3.2 security rules running on my new VPS (Virtualmin).

I enabled the REQUEST-903.9002-WORDPRESS-EXCLUSION-RULES, and it mostly seem to work.

The Wordpress theme editor, however, does not. When saving, it gets a 403 response ("Saving failed").

I know it's Modsecurity because when I disable it everything works fine.

I investigated the audit log and have created corresponding rules in REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf:

SecRule REQUEST_URI "@contains /wp-json/wp/v2/template-parts/" \
"id:10000002,\
phase:2,\
pass,\
nolog,\
ctl:ruleRemoveTargetById=949110;ARGS=content,\
ctl:ruleRemoveTargetById=941100;ARGS=content,\
ctl:ruleRemoveTargetById=941160;ARGS=content,\
ctl:ruleRemoveTargetById=941180;ARGS=content,\
ctl:ruleRemoveTargetById=932105;ARGS=content,\
ctl:ruleRemoveTargetById=980130;ARGS=content"

SecRule REQUEST_URI "@contains /wp-json/wp/v2/templates/<hostname>/page/" \
"id:10000003,\
phase:2,\
pass,\
nolog,\
ctl:ruleRemoveTargetById=949110;ARGS=content,\
ctl:ruleRemoveTargetById=941100;ARGS=content,\
ctl:ruleRemoveTargetById=941160;ARGS=content,\
ctl:ruleRemoveTargetById=941180;ARGS=content,\
ctl:ruleRemoveTargetById=932105;ARGS=content,\
ctl:ruleRemoveTargetById=980130"

I know the rules are being read, because when I mess with the request uri I can get Wordpress to stop working altogether.

However, the problem persist. I am not a Modsecurity expert; I understand my exclusion rules are not properly written, but I cannot get them to work.

Here's a few samples of the false positives from the Audit log, triggered by the Wordpress theme editor:

--48163009-H--
Message: Warning. Pattern match "(?:;|\\{|\\||\\|\\||&|&&|\\n|\\r|\\$\\(|\\$\\(\\(|`|\\${|<\\(|>\\(|\\(\\s*\\))\\s*(?:{|\\s*\\(\\s*|\\w+=(?:[^\\s]*|\\$.*|\\$.*|<.*|>.*|\\'.*\\'|\".*\")\\s+|!\\s*|\\$)*\\s*(?:'|\")*(?:[\\?\\*\\[\\]\\(\\)\\-\\|+\\w'\"\\./\\\\]+/)?[\\\\'\"]*(?:s[\\\\'\"]* ..." at ARGS:content. [file "/etc/modsecurity/rules/REQUEST-932-APPLICATION-ATTACK-RCE.conf"] [line "158"] [id "932105"] [msg "Remote Command Execution: Unix Command Injection"] [data "Matched Data: {\x22top found within ARGS:content: <!-- wp:template-part {\x22slug\x22:\x22header\x22,\x22theme\x22:\x22<hostname>\x22,\x22tagName\x22:\x22header\x22} /-->\x0a\x0a<!-- wp:group {\x22tagName\x22:\x22main\x22,\x22style\x22:{\x22spacing\x22:{\x22padding\x22:{\x22top\x22:\x220\x22,\x22right\x22:\x220\x22,\x22bottom\x22:\x220\x22,\x22left\x22:\x220\x22},\x22blockGap\x22:\x220\x22}}} -->\x0a<main class=\x22wp-block-group\x22 style=\x22padding-top:0;padding-right:0;padding-bottom:0;padding-left:0\x2..."] [severity "CRITICAL"] [ver "OWASP_CRS/3.3.2"]



Message: Warning. detected XSS using libinjection. [file "/etc/modsecurity/rules/REQUEST-941-APPLICATION-ATTACK-XSS.conf"] [line "55"] [id "941100"] [msg "XSS Attack Detected via libinjection"] [data "Matched Data: XSS data found within ARGS:content: <!-- wp:template-part {\x22slug\x22:\x22header\x22,\x22theme\x22:\x22<hostname>\x22,\x22tagName\x22:\x22header\x22} /-->\x0a\x0a<!-- wp:group {\x22tagName\x22:\x22main\x22,\x22style\x22:{\x22spacing\x22:{\x22padding\x22:{\x22top\x22:\x220\x22,\x22right\x22:\x220\x22,\x22bottom\x22:\x220\x22,\x22left\x22:\x220\x22},\x22blockGap\x22:\x220\x22}}} -->\x0a<main class=\x22wp-block-group\x22 style=\x22padding-top:0;padding-right:0;padding-bottom:0;padding-left:0\x2..."] [severity "CRITICAL"] [ver "OWASP_CRS/3.3.2"] [tag "application-multi"] [tag "language-multi"] [tag "platform-multi"] [tag "attack-xss"] [tag "paranoia-level/1"] [tag "OWASP_CRS"] [tag "capec/1000/152/242"]

Apache-Error: [file "apache2_util.c"] [line 273] [level 3] ModSecurity: Warning. Matched phrase "<!--" at ARGS:content. [file "/etc/modsecurity/rules/REQUEST-941-APPLICATION-ATTACK-XSS.conf"] [line "250"] [id "941180"] [msg "Node-Validator Blacklist Keywords"] [data "Matched Data: <!-- found within ARGS:content: <!-- wp:template-part {\\\\x22slug\\\\x22:\\\\x22header\\\\x22,\\\\x22theme\\\\x22:\\\\x22<hostname>\\\\x22,\\\\x22tagname\\\\x22:\\\\x22header\\\\x22} /-->\\\\x0a\\\\x0a<!-- wp:group {\\\\x22tagname\\\\x22:\\\\x22main\\\\x22,\\\\x22style\\\\x22:{\\\\x22spacing\\\\x22:{\\\\x22padding\\\\x22:{\\\\x22top\\\\x22:\\\\x220\\\\x22,\\\\x22right\\\\x22:\\\\x220\\\\x22,\\\\x22bottom\\\\x22:\\\\x220\\\\x22,\\\\x22left\\\\x22:\\\\x220\\\\x22},\\\\x22blockgap\\\\x22:\\\\x220\\\\x22}}} -->\\\\x0a<main class=\\\\x22wp-block-group\\\\x22 style=\\\\x22padding-top:0;padding-right:0;padding-bottom:0;padding-left:0\\\\x22><!..."] [severity "CRITICAL"] [ver "OWASP_CRS/3.3.2"] [tag "application-multi"] [tag "language-multi"] [tag "platform-multi"] [tag "attack-xss"] [tag "paranoia-level/1"] [tag "OWASP_CRS"] [tag "capec/1000/152/242"] [hostname "sit.<hostname>.com"] [uri "/wp-json/wp/v2/templates/<hostname>/page"] [unique_id "Y7-6B6WOVEBhE0cscXvdvgAAERU"]
Apache-Error: [file "apache2_util.c"] [line 273] [level 3] [client 92.46.0.178] ModSecurity: Access denied with code 403 (phase 2). Operator GE matched 5 at TX:anomaly_score. [file "/etc/modsecurity/rules/REQUEST-949-BLOCKING-EVALUATION.conf"] [line "93"] [id "949110"] [msg "Inbound Anomaly Score Exceeded (Total Score: 20)"] [severity "CRITICAL"] [ver "OWASP_CRS/3.3.2"] [tag "application-multi"] [tag "language-multi"] [tag "platform-multi"] [tag "attack-generic"] [hostname "<hostname>.com"] [uri "/wp-json/wp/v2/templates/<hostname>/page"] [unique_id "Y7-6B6WOVEBhE0cscXvdvgAAERU"]

================================================

[EDIT] For anybody interested, this was SOLVED by changing the rule as such:

SecRule REQUEST_URI "@beginsWith /wp-json/wp/v2/template" \
"id:10000002,\
phase:2,\
pass,\
nolog,\
ctl:ruleRemoveTargetById=941100;ARGS:content,\
ctl:ruleRemoveTargetById=941160;ARGS:content,\
ctl:ruleRemoveTargetById=941180;ARGS:content,\
ctl:ruleRemoveTargetById=932105;ARGS:content"

I merged the two block of rules into one, and changed = to : as suggested by azurit. Thanks!


Solution

  • Never exclude rules 949XXX and 980XXX as it's the same as completely disabling CRS.

    Your rules are more or less correct except this syntax problem:

    ARGS=content
    

    It should be:

    ARGS:content