coreruleset / wordpress-rule-exclusions-plugin

Rule exclusion plugin for WordPress.
Apache License 2.0
10 stars 6 forks source link

CRS breaks WP Githuber MD #60

Closed gene1wood closed 2 weeks ago

gene1wood commented 2 weeks ago

I'm unsure if this is the right place to report this. Any guidance is most welcome. I could imagine these paths

The problem

The WP Githuber MD Wordpress plugin (which is developed in https://github.com/terrylinooo/githuber-md ) causes all posts to be blocked by modsecurity with CRS.

The plugin uses an argument called h2m_strip_tags which triggers

ModSecurity: Warning. Matched phrase "strip_tags" at ARGS_NAMES:h2m_strip_tags. [file "/etc/modsecurity/crs/rules/REQUEST-933-APPLICATION-ATTACK-PHP.conf"] [line "300"] [id "933150"] [msg "PHP Injection Attack: High-Risk PHP Function Name Found"]

and blocks posting pages or posts

A local workaround

This is probably too broad as it disables all PHP injection protection from the post.php interface but it did enable me to make my page update

    <locationmatch "/wp-admin/post.php">
        SecRuleRemoveById 933150
    </locationmatch>

Logs

error.log

[Thu Aug 29 17:43:54.774025 2024] [:error] [pid 505201] [client 157.131.34.81:42838] [client 157.131.34.81] ModSecurity: Warning. Matched phrase "strip_tags" at ARGS_NAMES:h2m_strip_tags. [file "/etc/modsecurity/crs/rules/REQUEST-933-APPLICATION-ATTACK-PHP.conf"] [line "300"] [id "933150"] [msg "PHP Injection Attack: High-Risk PHP Function Name Found"] [data "Matched Data: strip_tags found within ARGS_NAMES:h2m_strip_tags: h2m_strip_tags"] [severity "CRITICAL"] [ver "OWASP_CRS/4.6.0-dev"] [tag "application-multi"] [tag "language-php"] [tag "platform-multi"] [tag "attack-injection-php"] [tag "paranoia-level/1"] [tag "OWASP_CRS"] [tag "capec/1000/152/242"] [hostname "wordpress.example.com"] [uri "/wp-admin/post.php"] [unique_id "ZtCzWo4QOupqaZbdCBd4rgAAABE"], referer: https://wordpress.example.com/wp-admin/post.php?post=281&action=edit
[Thu Aug 29 17:43:54.893259 2024] [:error] [pid 505201] [client 157.131.34.81:42838] [client 157.131.34.81] ModSecurity: Access denied with code 403 (phase 2). Operator GE matched 5 at TX:blocking_inbound_anomaly_score. [file "/etc/modsecurity/crs/rules/REQUEST-949-BLOCKING-EVALUATION.conf"] [line "233"] [id "949110"] [msg "Inbound Anomaly Score Exceeded (Total Score: 5)"] [ver "OWASP_CRS/4.6.0-dev"] [tag "anomaly-evaluation"] [tag "OWASP_CRS"] [hostname "wordpress.example.com"] [uri "/wp-admin/post.php"] [unique_id "ZtCzWo4QOupqaZbdCBd4rgAAABE"], referer: https://wordpress.example.com/wp-admin/post.php?post=281&action=edit
[Thu Aug 29 17:43:54.893719 2024] [:error] [pid 505201] [client 157.131.34.81:42838] [client 157.131.34.81] ModSecurity: Warning. Unconditional match in SecAction. [file "/etc/modsecurity/crs/rules/RESPONSE-980-CORRELATION.conf"] [line "98"] [id "980170"] [msg "Anomaly Scores: (Inbound Scores: blocking=5, detection=5, per_pl=5-0-0-0, threshold=5) - (Outbound Scores: blocking=0, detection=0, per_pl=0-0-0-0, threshold=4) - (SQLI=0, XSS=0, RFI=0, LFI=0, RCE=0, PHPI=5, HTTP=0, SESS=0, COMBINED_SCORE=5)"] [ver "OWASP_CRS/4.6.0-dev"] [tag "reporting"] [tag "OWASP_CRS"] [hostname "wordpress.example.com"] [uri "/wp-admin/post.php"] [unique_id "ZtCzWo4QOupqaZbdCBd4rgAAABE"], referer: https://wordpress.example.com/wp-admin/post.php?post=281&action=edit

modsecurity audit log

--ddcc4c18-A--
[29/Aug/2024:17:43:54 +0000] ZtCzWo4QOupqaZbdCBd4rgAAABE 157.131.34.81 42838 51.81.82.182 443
--ddcc4c18-B--
POST /wp-admin/post.php HTTP/1.1
Host: wordpress.example.com
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:129.0) Gecko/20100101 Firefox/129.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/png,image/svg+xml,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br, zstd
Referer: https://wordpress.example.com/wp-admin/post.php?post=281&action=edit
Content-Type: application/x-www-form-urlencoded
Content-Length: 5510
Origin: https://wordpress.example.com
Connection: keep-alive
Cookie: __gads=ID=08e528c41accecee:T=1712177113:RT=1724622035:S=ALNI_MZSXVWBAv-yskd55n4joZXRqYGu5A; __gpi=UID=00000ddbb51d85cb:T=1712177113:RT=1724622035:S=ALNI_MbDJjH3NBNjJbVKdm-gsVo_UUxjuA; __eoi=ID=264865f8bfbccb6e:T=1712177113:RT=1724622035:S=AA-AfjaSn5oTbWuIPvhirM6lylQi; __utma=31034925.2110713176.1716236684.1716236684.1716236684.1; __utmz=31034925.1716236684.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none); __utma=134134684.2080635909.1719984988.1724641726.1724951925.9; __utmz=134134684.1719984988.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none); wp-settings-1=m0%3Do%26m9%3Do%26m8%3Do%26editor%3Dhtml%26m3%3Do%26m5%3Do%26m4%3Do%26m6%3Do%26m1%3Do%26m2%3Do%26m7%3Do%26m10%3Do%26imgsize%3Dfull%26libraryContent%3Dbrowse%26align%3Dnone%26urlbutton%3Dnone; wp-settings-time-1=1719984997; wordpress_google_apps_login=a17db2b416959861b185a98a5ec93158; __utmc=134134684; wordpress_test_cookie=WP%20Cookie%20check; wp_lang=en_US; __utmc=31034925; __utmb=134134684.1.10.1724951925; wordpress_sec_afe1883185e32a556ef5a2ddb58fb1f1=ge_REDACTED_97; wordpress_logged_in_afe1883185e32a556ef5a2ddb58fb1f1=ge_REDACTED_41
Upgrade-Insecure-Requests: 1
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: same-origin
Sec-Fetch-User: ?1
Priority: u=0, i

--ddcc4c18-C--
_wpnonce=a0a494a4bd&_wp_http_referer=%2Fwp-admin%2Fpost.php%3Fpost%3D281%26action%3Dedit&user_ID=1&action=editpost&originalaction=editpost&post_author=1&post_type=page&original_post_status=publish&referredby=https%3A%2F%2Fwordpress.example.com%2Fcontact%2F&_wp_original_http_referer=https%3A%2F%2Fwordpress.example.com%2Fcontact%2F&post_ID=281&meta-box-order-nonce=3c0d4f4f0a&closedpostboxesnonce=c19c91a0db&post_title=Contact&samplepermalinknonce=5712067a04&content=%23_REDACTED_%29&markdown_this_post=yes&h2m_strip_tags=yes&h2m_line_break=yes&wp-preview=&hidden_post_status=publish&post_status=publish&hidden_post_password=&hidden_post_visibility=public&visibility=public&post_password=&mm=02&jj=22&aa=2012&hh=15&mn=57&ss=56&hidden_mm=02&cur_mm=08&hidden_jj=22&cur_jj=29&hidden_aa=2012&cur_aa=2024&hidden_hh=15&cur_hh=09&hidden_mn=57&cur_mn=19&original_publish=Update&save=Update&parent_id=&menu_order=0&wordpress-https=da2dfadbe9&_wp_http_referer=%2Fwp-admin%2Fpost.php%3Fpost%3D281%26action%3Dedit&_thumbnail_id=-1&metakeyinput=&metavalue=&_ajax_nonce-add-meta=5d973b5395&advanced_view=1&add_comment_nonce=2da8cf5537&_ajax_fetch_list_nonce=922778764d&_wp_http_referer=%2Fwp-admin%2Fpost.php%3Fpost%3D281%26action%3Dedit&post_name=contact&post_author_override=1
--ddcc4c18-F--
HTTP/1.1 403 Forbidden
Content-Length: 286
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: text/html; charset=iso-8859-1

--ddcc4c18-E--
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>403 Forbidden</title>
</head><body>
<h1>Forbidden</h1>
<p>You don't have permission to access this resource.</p>
<hr>
<address>Apache/2.4.41 (Ubuntu) Server at wordpress.example.com Port 443</address>
</body></html>

--ddcc4c18-H--
Message: Warning. Matched phrase "strip_tags" at ARGS_NAMES:h2m_strip_tags. [file "/etc/modsecurity/crs/rules/REQUEST-933-APPLICATION-ATTACK-PHP.conf"] [line "300"] [id "933150"] [msg "PHP Injection Attack: High-Risk PHP Function Name Found"] [data "Matched Data: strip_tags found within ARGS_NAMES:h2m_strip_tags: h2m_strip_tags"] [severity "CRITICAL"] [ver "OWASP_CRS/4.6.0-dev"] [tag "application-multi"] [tag "language-php"] [tag "platform-multi"] [tag "attack-injection-php"] [tag "paranoia-level/1"] [tag "OWASP_CRS"] [tag "capec/1000/152/242"]
Message: Access denied with code 403 (phase 2). Operator GE matched 5 at TX:blocking_inbound_anomaly_score. [file "/etc/modsecurity/crs/rules/REQUEST-949-BLOCKING-EVALUATION.conf"] [line "233"] [id "949110"] [msg "Inbound Anomaly Score Exceeded (Total Score: 5)"] [ver "OWASP_CRS/4.6.0-dev"] [tag "anomaly-evaluation"] [tag "OWASP_CRS"]
Message: Warning. Unconditional match in SecAction. [file "/etc/modsecurity/crs/rules/RESPONSE-980-CORRELATION.conf"] [line "98"] [id "980170"] [msg "Anomaly Scores: (Inbound Scores: blocking=5, detection=5, per_pl=5-0-0-0, threshold=5) - (Outbound Scores: blocking=0, detection=0, per_pl=0-0-0-0, threshold=4) - (SQLI=0, XSS=0, RFI=0, LFI=0, RCE=0, PHPI=5, HTTP=0, SESS=0, COMBINED_SCORE=5)"] [ver "OWASP_CRS/4.6.0-dev"] [tag "reporting"] [tag "OWASP_CRS"]
Apache-Error: [file "apache2_util.c"] [line 271] [level 3] [client 157.131.34.81] ModSecurity: Warning. Matched phrase "strip_tags" at ARGS_NAMES:h2m_strip_tags. [file "/etc/modsecurity/crs/rules/REQUEST-933-APPLICATION-ATTACK-PHP.conf"] [line "300"] [id "933150"] [msg "PHP Injection Attack: High-Risk PHP Function Name Found"] [data "Matched Data: strip_tags found within ARGS_NAMES:h2m_strip_tags: h2m_strip_tags"] [severity "CRITICAL"] [ver "OWASP_CRS/4.6.0-dev"] [tag "application-multi"] [tag "language-php"] [tag "platform-multi"] [tag "attack-injection-php"] [tag "paranoia-level/1"] [tag "OWASP_CRS"] [tag "capec/1000/152/242"] [hostname "wordpress.example.com"] [uri "/wp-admin/post.php"] [unique_id "ZtCzWo4QOupqaZbdCBd4rgAAABE"]
Apache-Error: [file "apache2_util.c"] [line 271] [level 3] [client 157.131.34.81] ModSecurity: Access denied with code 403 (phase 2). Operator GE matched 5 at TX:blocking_inbound_anomaly_score. [file "/etc/modsecurity/crs/rules/REQUEST-949-BLOCKING-EVALUATION.conf"] [line "233"] [id "949110"] [msg "Inbound Anomaly Score Exceeded (Total Score: 5)"] [ver "OWASP_CRS/4.6.0-dev"] [tag "anomaly-evaluation"] [tag "OWASP_CRS"] [hostname "wordpress.example.com"] [uri "/wp-admin/post.php"] [unique_id "ZtCzWo4QOupqaZbdCBd4rgAAABE"]
Apache-Error: [file "apache2_util.c"] [line 271] [level 3] [client 157.131.34.81] ModSecurity: Warning. Unconditional match in SecAction. [file "/etc/modsecurity/crs/rules/RESPONSE-980-CORRELATION.conf"] [line "98"] [id "980170"] [msg "Anomaly Scores: (Inbound Scores: blocking=5, detection=5, per_pl=5-0-0-0, threshold=5) - (Outbound Scores: blocking=0, detection=0, per_pl=0-0-0-0, threshold=4) - (SQLI=0, XSS=0, RFI=0, LFI=0, RCE=0, PHPI=5, HTTP=0, SESS=0, COMBINED_SCORE=5)"] [ver "OWASP_CRS/4.6.0-dev"] [tag "reporting"] [tag "OWASP_CRS"] [hostname "wordpress.example.com"] [uri "/wp-admin/post.php"] [unique_id "ZtCzWo4QOupqaZbdCBd4rgAAABE"]
Action: Intercepted (phase 2)
Apache-Handler: proxy:unix:/run/php/php8.3-fpm.sock|fcgi://localhost
Stopwatch: 1724953434715998 180227 (- - -)
Stopwatch2: 1724953434715998 180227; combined=176483, p1=2687, p2=173506, p3=0, p4=0, p5=290, sr=0, sw=0, l=0, gc=0
Response-Body-Transformed: Dechunked
Producer: ModSecurity for Apache/2.9.3 (http://www.modsecurity.org/); OWASP_CRS/4.6.0-dev.
Server: Apache/2.4.41 (Ubuntu)
Engine-Mode: "ENABLED"

--ddcc4c18-Z--
EsadCetiner commented 2 weeks ago

@gene1wood Unfortunately the WordPress plugin only supports Vanilla WordPress, false positives that are due to a plugin must be resolved via a custom rule exclusion.

This is probably too broad as it disables all PHP injection protection from the post.php interface but it did enable me to make my page update

Yes your right, that rule exclusion is too broad, you can disable a rule for specific targets by using SecRuleUpdateTargetById instead of disabling the rule completely. It should look something like this:

    <locationmatch "/wp-admin/post.php">
        SecRuleUpdateTargetById 933150 "!ARGS_NAMES:h2m_strip_tags"
    </locationmatch>
gene1wood commented 2 weeks ago

Thanks @EsadCetiner . I had to move the SecRuleUpdateTargetById directive outside of VirtualHost and outside of LocationMatch to get it to work as it sounds from this issue https://github.com/owasp-modsecurity/ModSecurity/issues/89 that in modesecurity 2.9.x it won't work in those blocks.

Anyhow, thanks for the pointer to the custom rule exclusion.