Parsing error when submitting file with an apostrophe (') in filename · Issue #2352 · owasp-modsecurity/ModSecurity (original) (raw)
Describe the bug
When submitting a file with an apostrophe (') in the filename, ModSecurity fails to parse the request body causing the ModSecurity Recommended Rules to deny the request.
Logs and dumps
2020/07/07 15:03:49 [warn] 26375#26375: *1 [client 127.0.0.1] ModSecurity: Warning. Matched "Operator `Eq' with parameter `0' against variable `MULTIPART_STRICT_ERROR' (Value: `1' ) [file "conf/modsecurity.conf"] [line "30"] [id "200003"] [rev ""] [msg "Multipart request body failed strict validation: PE 0, BQ 0, BW 0, DB 0, DA 0, HF 0, LF 0, SM 0, IQ 1, IP 0, IH 0, FL "] [data ""] [severity "0"] [ver ""] [maturity "0"] [accuracy "0"] [hostname "127.0.0.1"] [uri "/"] [unique_id "159413422979.139957"] [ref "v173,1"], client: 127.0.0.1, server: localhost, request: "POST / HTTP/1.1", host: "localhost"
---h0TpBzpy---A--
[07/Jul/2020:15:03:49 +0000] 159413422979.139957 127.0.0.1 51588 127.0.0.1 80
---h0TpBzpy---B--
POST / HTTP/1.1
Host: localhost User-Agent: curl/7.64.0 Accept: */*
Content-Length: 215
Content-Type: multipart/form-data; boundary=------------------------31e93f28b36621f5
---h0TpBzpy---C--
--------------------------31e93f28b36621f5
Content-Disposition: form-data; name="filename"; filename="it's_a_test.txt"
Content-Type: text/plain
TEST_FILE_CONTENT
--------------------------31e93f28b36621f5--
---h0TpBzpy---D--
---h0TpBzpy---F--
HTTP/1.1 400
Server: nginx
Date: Tue, 07 Jul 2020 15:03:49 GMT
Content-Length: 166
Content-Type: text/html
Connection: close
---h0TpBzpy---G--
---h0TpBzpy---H--
ModSecurity: Access denied with code 400 (phase 2). Matched "Operator `Eq' with parameter `0' against variable `MULTIPART_STRICT_ERROR' (Value: `1' ) [file "conf/modsecurity.conf"] [line "30"] [id "200003"] [rev ""] [msg "Multipart reque$
t body failed strict validation: PE 0, BQ 0, BW 0, DB 0, DA 0, HF 0, LF 0, SM 0, IQ 1, IP 0, IH 0, FL "] [data ""] [severity "0"] [ver ""] [maturity "0"] [accuracy "0"] [hostname "127.0.0.1"] [uri "/"] [unique_id "159413422979.139957"] [$
ef "v173,1"]
---h0TpBzpy---I--
---h0TpBzpy---J--
---h0TpBzpy---Z--
To Reproduce
- Set up environment: https://www.netnea.com/cms/nginx-modsecurity-tutorials/
- Create test files (one with, one without apostrophe):
echo "TEST_FILE_CONTENT" > its_a_test.txt cp its_a_test.txt "it's_a_test.txt"
- Perform working request (without apostrophe):
curl -F "filename=@its_a_test.txt" localhost
<html>
<head><title>405 Not Allowed</title></head>
<body bgcolor="white">
<center><h1>405 Not Allowed</h1></center>
<hr><center>nginx</center>
</body>
</html>
- Perform failing equest (with apostrophe):
curl -F "filename=@it's_a_test.txt" localhost
<html>
<head><title>400 Bad Request</title></head>
<body bgcolor="white">
<center><h1>400 Bad Request</h1></center>
<hr><center>nginx</center>
</body>
</html>
Expected behavior
See working request above. ModSec should not intervene.
Server (please complete the following information):
- ModSecurity version (and connector): modsecurity-v3.0.0 with modsecurity-nginx-v1.0.0
- WebServer: nginx-1.13.9
- OS (and distro): Debian GNU/Linux 10
Rule Set (please complete the following information):
Using minimal configuration:
$ cat /opt/nginx-1.13.9/conf/nginx.conf
daemon off;
worker_processes 2;
user www-data;
load_module modules/ngx_http_modsecurity_module.so;
events {
use epoll;
worker_connections 128;
}
error_log logs/error.log info;
http {
modsecurity on;
server_tokens off;
include mime.types;
charset utf-8;
modsecurity_rules_file conf/modsecurity.conf;
access_log logs/access.log combined;
server {
server_name localhost;
listen 0.0.0.0:80;
error_page 500 502 503 504 /50x.html;
location / {
root html;
}
}
}
$ cat /opt/nginx-1.13.9/conf/modsecurity.conf
SecRuleEngine On
SecRequestBodyAccess On
SecRequestBodyLimit 13107200
SecRequestBodyNoFilesLimit 64000
SecResponseBodyAccess On
SecResponseBodyLimit 10000000
SecTmpDir /tmp/
SecDataDir /tmp/
SecUploadDir /tmp/
SecAuditEngine On
SecAuditLogRelevantStatus "^(?:5|4(?!04))"
SecAuditLogParts ABCDEFGHIJZ
SecAuditLogType Serial
SecAuditLog logs/modsec_audit.log
SecAuditLogStorageDir logs/audit
SecDebugLog logs/modsec_debug.log
SecDebugLogLevel 0
SecRule REQUEST_HEADERS:Content-Type "(?:application(?:/soap\+|/)|text/)xml" \
"id:200000,phase:1,t:none,t:lowercase,pass,nolog,ctl:requestBodyProcessor=XML"
SecRule REQUEST_HEADERS:Content-Type "application/json" \
"id:200001,phase:1,t:none,t:lowercase,pass,nolog,ctl:requestBodyProcessor=JSON"
SecRule REQBODY_ERROR "!@eq 0" \
"id:200002,phase:2,t:none,deny,status:400,log,\
msg:'Failed to parse request body.',logdata:'%{reqbody_error_msg}',severity:2"
SecRule MULTIPART_STRICT_ERROR "!@eq 0" \
"id:200003,phase:2,t:none,deny,status:400,log, \
msg:'Multipart request body failed strict validation: PE %{REQBODY_PROCESSOR_ERROR}, BQ %{MULTIPART_BOUNDARY_QUOTED}, BW %{MULTIPART_BOUNDARY_WHITESPACE}, DB %{MULTIPART_DATA_BEFORE}, DA %{MULTIPART_DATA_AFTER}, HF %{MULTIPART_HEADER_FOLDING}, LF %{MULTIPART_LF_LINE}, SM %{MULTIPART_MISSING_SEMICOLON}, IQ %{MULTIPART_INVALID_QUOTING}, IP %{MULTIPART_INVALID_PART}, IH %{MULTIPART_INVALID_HEADER_FOLDING}, FL %{MULTIPART_FILE_LIMIT_EXCEEDED}'"
SecRule TX:/^MSC_/ "!@streq 0" \
"id:200005,phase:2,t:none,deny,status:500,\
msg:'ModSecurity internal error flagged: %{MATCHED_VAR_NAME}'"