owasp-modsecurity / ModSecurity-nginx

ModSecurity v3 Nginx Connector
Apache License 2.0
1.58k stars 282 forks source link

Content type header false positive after NGINX version 1.23.0 update #284

Closed justas147 closed 2 years ago

justas147 commented 2 years ago

After updating NGINX version to 1.23.0 and rebuilding both libmodsecurity and ModSecurity-nginx connector I start to get false positives with ModSecurity Core Rule Set:

---AyeE7oHW---H--
ModSecurity: Access denied with code 403 (phase 1). Matched "Operator `Rx' with parameter `^[\w/.+-]+(?:\s?;\s?(?:action|boundary|charset|type|start(?:-info)?)\s?=\s?['\"\w.()+,/:=?<>@-]+)*$' against variable `REQUEST_HEADERS:content-type' (Value: `application/x-www-form-urlencoded; charset=UTF-8' ) [file "/etc/nginx/modsec/coreruleset/rules/REQUEST-920-PROTOCOL-ENFORCEMENT.conf"] [line "915"] [id "920470"] [rev ""] [msg "Illegal Content-Type header"] [data "application/x-www-form-urlencoded; charset=utf-8"] [severity "2"] [ver "OWASP_CRS/3.3.2"] [maturity "0"] [accuracy "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"]

I'm not sure if it has something to do with the new version or if I missed something?

Versions: NGINX - 1.23.0 ModSecurity-nginx connector - v1.0.3 libmodsecurity - v3.0.6

martinhsv commented 2 years ago

@justas147 ,

First, since you didn't mention it, I'll highlight that ModSecurity v3.0.6 does not support PCRE2, which recent versions of nginx use by default. If using such versions of nginx with ModSecurity v3.0.6, then you must build the connector using the --without-pcre2 flag. (See, for example, https://github.com/SpiderLabs/ModSecurity-nginx/issues/261#issuecomment-1002479785 )

Assuming the content is indeed (as indicated by your 'Section H' output) the following, with no unseen special characters:

Content-Type: application/x-www-form-urlencoded; charset=utf-8

... then I would not expect that particular CRS rule to result in match. And, indeed, it did not in the test that I just did.

justas147 commented 2 years ago

Thank you for the response. I updated libmodsecurity to version v3.0.7 and that particular false positive no longer appears. However, there is still one rule being matched:

---Nry8Tnfd---B--
POST /index.php HTTP/2.0
x-requested-with: XMLHttpRequest
content-type: application/x-www-form-urlencoded; charset=UTF-8
user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36
sec-fetch-site: same-origin
accept: application/json, text/javascript, */*; q=0.01
sec-ch-ua: ".Not/A)Brand";v="99", "Google Chrome";v="103", "Chromium";v="103"
sec-ch-ua-platform: "Windows"
content-length: 115
...

---Nry8Tnfd---D--

---Nry8Tnfd---F--
HTTP/2.0 403

---Nry8Tnfd---H--
ModSecurity: Access denied with code 403 (phase 1). Matched "Operator `Rx' with parameter `^\d+$' against variable `REQUEST_HEADERS:content-length' (Value: `115' ) [file "/etc/nginx/modsec/coreruleset/rules/REQUEST-920-PROTOCOL-ENFORCEMENT.conf"] [line "127"] [id "920160"] [rev ""] [msg "Content-Length HTTP header is not numeric"] [data "115"] [severity "2"] [ver "OWASP_CRS/3.3.2"] [maturity "0"] [accuracy "0"] [tag "application-multi"] [tag "language-multi"] [tag "platform-multi"] [tag "attack-protocol"] [tag "paranoia-level/1"] [tag "OWASP_CRS"] [tag "capec/1000/210/272"]

In debug log I can see a lot of Error with regular expression logs:

[1657227785] [/index.php] [3] Error with regular expression: "^\d+$"

Does this log indicate a problem with PCRE library?

martinhsv commented 2 years ago

That DebugLog message indicates that an attempt was made to use a regular expression that was not successfully compiled.

The expected use case for such messages is if the user writes a rule with an invalid regex.

E.g. "@rx aa(bb" cannot be compiled because of the unbalance parentheses.

In your case, the fact that ModSecurity does not have a properly compiled regex is consistent with getting a false positive on that rule. I.e. In addition to producing the error message, the code is defaulting to 'not found' for the regex match -- and since CRS rule 920160 has a "not" before the operator "!@rx ^\d+$", it results in a match for the rule.

The main question would then be why the regular expression failed to compile. There is nothing wrong with '^\d+$'.

I would still suspect conflict between PCRE1 and PCRE2. Note that if you are using ModSecurity v3.0.7 and you want to use PCRE2, you must specify that during the configure step: ./configure --with-pcre2 per https://github.com/SpiderLabs/ModSecurity/pull/2719

justas147 commented 2 years ago

After configuring with --with-pcre2 flag the error no longer appears. Thank you so much for the help!