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

echo "TEST_FILE_CONTENT" > its_a_test.txt cp its_a_test.txt "it's_a_test.txt"

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>

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):

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}'"