Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Modsecurity v3 : nginx POST data not printed into auditlog #2529

Closed
cello86 opened this issue Mar 10, 2021 · 13 comments
Closed

Modsecurity v3 : nginx POST data not printed into auditlog #2529

cello86 opened this issue Mar 10, 2021 · 13 comments
Assignees

Comments

@cello86
Copy link

cello86 commented Mar 10, 2021

We tried to configure the logging of Request Body for blocked request via Nginx + modsecurity v3 but don't have the printed options H and C. The config of SecAuditLogParts is ABCIJDEFHZ and we noticed that this rule doesn't print the action options (suggested info owasp-modsecurity/ModSecurity-nginx#76).

        location @403_json {
            default_type application/json;
            #issue https://github.com/SpiderLabs/ModSecurity-nginx/issues/76
            modsecurity_rules 'SecRule REQUEST_URI "@beginsWith /" "id:1,pass,phase:2,log,ctl:ruleEngine=DetectionOnly"';
            return 403 '{"code": 403, "desciption": "error"}';
        }

Logs and dumps
N/A

Server (please complete the following information):

  • ModSecurity version (and connector): ModSecurity v3.0.3 with nginx-connector v1.0.0
  • WebServer: nginx-1.19.7
  • OS (and distro): CentOS 7.9

Rule Set (please complete the following information):

  • Running any public or commercial rule set? OWASP CRS
  • What is the version number? 3.2.0
@martinhsv martinhsv self-assigned this Mar 11, 2021
@martinhsv
Copy link
Contributor

Hi @cello86,

I'm not completely clear on the problem you are outlining. From your first sentence, it sounded like you were talking about an overall issue with section 'C' output not appearing in the audit log, but from the later pasted content it sounds like you are talking about only an error-page redirection scenario.

I have just checked and section C output is generally available in v3.0.3.

You are using older versions of both ModSecurity and the nginx connector. There are important fixes related to both logging and error-page redirects in more recent versions of both. My main suggestion would be to upgrade to v3.0.4 and v1.0.1 respectively.

@cello86
Copy link
Author

cello86 commented Mar 11, 2021

Hi @martinhsv,
We already updated the version of nginx connector to 1.0.1 but we had to rollback the change for this issue owasp-modsecurity/ModSecurity-nginx#176.

Marcello

@martinhsv
Copy link
Contributor

So, are you saying you are re-reporting the issue owasp-modsecurity/ModSecurity-nginx#176 that was closed as a duplicate?

@cello86
Copy link
Author

cello86 commented Mar 11, 2021

No there are two different issues. Into the nginx-connector 1.0.1 whole audit log didn't work and in this issue with the nginx-connector the C part doesn't work.

@martinhsv
Copy link
Contributor

Did you try using v1.0.1 of the connector with the fix owasp-modsecurity/ModSecurity-nginx#175 as suggested by @victorhora here: owasp-modsecurity/ModSecurity-nginx#176 ?

@cello86
Copy link
Author

cello86 commented Mar 12, 2021

I tried to replicate all the scenarion and I started with:

  • nginx: 1.19.7
  • nginx-connector : 1.0.0
  • mod_security 3.0.4
  • OWASP CRS: 3.2.0
  • config SecAuditLogParts: "ABCIJDEFHZ"

Scenario 1.

Nginx basic configuration

Curl result
OK

# curl -i -k -XPOST https://test.local/test?path=../../../etc/hosts -d '{if code = 1}'
HTTP/1.1 403 Forbidden
Date: Fri, 12 Mar 2021 08:58:15 GMT
Content-Type: text/html
Content-Length: 158
Connection: keep-alive
Server: nginx

<html>
<head><title>403 Forbidden</title></head>
<body>
<center><h1>403 Forbidden</h1></center>
<hr><center>Nginx</center>
</body>
</html>

Audit log
OK

---NhWKcwC2---A--
[12/Mar/2021:09:58:15 +0100] 161553949595.090866 192.168.1.1 62978 192.168.1.1 443
---NhWKcwC2---B--
POST /test?path=../../../etc/hosts HTTP/1.1
Host: test.local
User-Agent: curl/7.65.0
Accept: */*
Content-Length: 13
Content-Type: application/x-www-form-urlencoded
---NhWKcwC2---C--
{if code = 1}
---NhWKcwC2---D--
---NhWKcwC2---F--
HTTP/1.1 403
Server: nginx
Date: Fri, 12 Mar 2021 08:58:15 GMT
Content-Length: 158
Content-Type: text/html
Connection: keep-alive
Via:
---NhWKcwC2---H--
ModSecurity: Warning. Matched "Operator XXX
ModSecurity: Warning. Matched "Operator XXX
ModSecurity: Warning. Matched "Operator XXX
---NhWKcwC2---I--
---NhWKcwC2---J--
---NhWKcwC2---Z--

Scenario 2

Nginx configuration with custom error page and fix reported to issue owasp-modsecurity/ModSecurity-nginx#76.

        error_page 403 @403_json;

        location @403_json {
            default_type application/json;

            modsecurity_rules 'SecRule REQUEST_URI "@beginsWith /" "id:1,pass,phase:2,log,ctl:ruleEngine=DetectionOnly"';
            return 403 '{"code": 403, "description": "error"}';
        }

Curl result
OK

curl -i -k -XPOST https://test.local/test?path=../../../etc/hosts -d '{if code = 1}'
HTTP/1.1 403 Forbidden
Date: Fri, 12 Mar 2021 09:07:49 GMT
Content-Type: application/json
Content-Length: 166
Connection: keep-alive
Server: nginx

{"code": 403, "description": "error"}         

Audit log
KO in this configuration we miss the header H and C

---onDx8gIg---A--
[12/Mar/2021:10:07:49 +0100] 161554006977.486138 192.168.1.1 63064 192.168.1.1 443
---onDx8gIg---B--
POST /test?path=../../../etc/hosts HTTP/1.1
Host: test.local
User-Agent: curl/7.65.0
Accept: */*
Content-Length: 13
Content-Type: application/x-www-form-urlencoded
---onDx8gIg---D--
---onDx8gIg---F--
HTTP/1.1 403
Server: nginx
Server: nginx
Date: Fri, 12 Mar 2021 09:07:49 GMT
Content-Length: 166
Content-Type: application/json
Connection: keep-alive
X-Powered-By: ASP.NET
Via:
---onDx8gIg---H--
---onDx8gIg---I--
---onDx8gIg---J--
---onDx8gIg---Z--

@cello86
Copy link
Author

cello86 commented Mar 12, 2021

I tried to replicate all the scenarion and I started with:

  • nginx: 1.19.7
  • nginx-connector : 1.0.1
  • mod_security 3.0.4
  • OWASP CRS: 3.2.0
  • config SecAuditLogParts: "ABCIJDEFHZ"

Scenario 1.

Nginx basic configuration

Curl result
OK

# curl -i -k -XPOST https://test.local/test?path=../../../etc/hosts -d '{if code = 1}'
HTTP/1.1 403 Forbidden
Date: Fri, 12 Mar 2021 09:21:32 GMT
Content-Type: text/html
Content-Length: 158
Connection: keep-alive
Server: nginx

<html>
<head><title>403 Forbidden</title></head>
<body>
<center><h1>403 Forbidden</h1></center>
<hr><center>Nginx</center>
</body>
</html>

Audit log
OK

---LzuBCjtw---A--
[12/Mar/2021:10:21:32 +0100] 161554089247.954903 192.168.1.1 63290 192.168.1.1 443
---LzuBCjtw---B--
POST /test?path=../../../etc/hosts HTTP/1.1
Host: test.local
User-Agent: curl/7.65.0
Accept: */*
Content-Length: 13
Content-Type: application/x-www-form-urlencoded
---LzuBCjtw---C--
{if code = 1}
---LzuBCjtw---D--
---LzuBCjtw---E--
<html>\x0d\x0a<head><title>403 Forbidden</title></head>\x0d\x0a<body>\x0d\x0a<center><h1>403 Forbidden</h1></center>\x0d\x0a<hr><center>nginx</center>\x0d\x0a</body>\x0d\x0a</html>\x0d\x0a
---LzuBCjtw---F--
HTTP/1.1 403
Server: nginx
Date: Fri, 12 Mar 2021 09:21:32 GMT
Content-Length: 158
Content-Type: text/html
Connection: keep-alive
X-Powered-By: ASP.NET
---LzuBCjtw---H--
ModSecurity: Warning. Matched "Operator XXX
ModSecurity: Warning. Matched "Operator XXX
ModSecurity: Warning. Matched "Operator XXX
---LzuBCjtw---I--
---LzuBCjtw---J--
---LzuBCjtw---Z--

Scenario 2

Nginx configuration with custom error page and fix reported to issue owasp-modsecurity/ModSecurity-nginx#76.

        error_page 403 @403_json;

        location @403_json {
            default_type application/json;

            modsecurity_rules 'SecRule REQUEST_URI "@beginsWith /" "id:1,pass,phase:2,log,ctl:ruleEngine=DetectionOnly"';
            return 403 '{"code": 403, "description": "error"}';
        }

Curl result
OK

curl -i -k -XPOST https://test.local/test?path=../../../etc/hosts -d '{if code = 1}'
HTTP/1.1 403 Forbidden
Date: Fri, 12 Mar 2021 09:07:49 GMT
Content-Type: application/json
Content-Length: 166
Connection: keep-alive
Server: nginx

{"code": 403, "description": "error"}         

Audit log
KO in this configuration we missed all the auditlog

@cello86
Copy link
Author

cello86 commented Mar 12, 2021

I tried to replicate all the scenarion and I started with:

Scenario 1.

Nginx basic configuration

Curl result
OK

# curl -i -k -XPOST https://test.local/test?path=../../../etc/hosts -d '{if code = 1}'
HTTP/1.1 403 Forbidden
Date: Fri, 12 Mar 2021 12:26:59 GMT
Content-Type: text/html
Content-Length: 158
Connection: keep-alive
Server: nginx

<html>
<head><title>403 Forbidden</title></head>
<body>
<center><h1>403 Forbidden</h1></center>
<hr><center>Nginx</center>
</body>
</html>

Audit log
OK

---2X3maK6X---A--
[12/Mar/2021:13:26:59 +0100] 161555201924.488672 192.168.1.1 50026 192.168.1.1 443
---2X3maK6X---B--
POST /test?path=../../../etc/hosts HTTP/1.1
Host: test.local
User-Agent: curl/7.65.0
Accept: */*
Content-Length: 13
Content-Type: application/x-www-form-urlencoded

---2X3maK6X---C--
{if code = 1}

---2X3maK6X---D--

---2X3maK6X---E--
<html>\x0d\x0a<head><title>403 Forbidden</title></head>\x0d\x0a<body>\x0d\x0a<center><h1>403 Forbidden</h1></center>\x0d\x0a<hr><center>nginx</center>\x0d\x0a</body>\x0d\x0a</html>\x0d\x0a

---2X3maK6X---F--
HTTP/1.1 403
Server: nginx
Date: Fri, 12 Mar 2021 12:26:59 GMT
Content-Length: 158
Content-Type: text/html
Connection: keep-alive
---2X3maK6X---H--
ModSecurity: Warning. Matched "Operator XXX
ModSecurity: Warning. Matched "Operator XXX
ModSecurity: Warning. Matched "Operator XXX
---2X3maK6X---I--
---2X3maK6X---J--
---2X3maK6X---Z--

Scenario 2

Nginx configuration with custom error page and fix reported to issue owasp-modsecurity/ModSecurity-nginx#76.

        error_page 403 @403_json;

        location @403_json {
            default_type application/json;

            modsecurity_rules 'SecRule REQUEST_URI "@beginsWith /" "id:1,pass,phase:2,log,ctl:ruleEngine=DetectionOnly"';
            return 403 '{"code": 403, "description": "error"}';
        }

Curl result
OK

curl -i -k -XPOST https://test.local/test?path=../../../etc/hosts -d '{if code = 1}'
HTTP/1.1 403 Forbidden
Date: Fri, 12 Mar 2021 12:29:04 GMT
Content-Type: application/json
Content-Length: 166
Connection: keep-alive
Server: nginx

{"code": 403, "description": "error"}         

Audit log
KO in this configuration we miss the header H and C

---ZHXBV3hl---A--
[12/Mar/2021:13:29:04 +0100] 161555214417.645866 192.168.1.1 50055 192.168.1.1 443
---ZHXBV3hl---B--
POST /test?path=../../../etc/hosts HTTP/1.1
Host: test.local
User-Agent: curl/7.65.0
Accept: */*
Content-Length: 13
Content-Type: application/x-www-form-urlencoded
---ZHXBV3hl---D--
---ZHXBV3hl---E--
{"code": 403, "description": "error"}
---ZHXBV3hl---F--
HTTP/1.1 403
Server: nginx
Date: Fri, 12 Mar 2021 12:29:04 GMT
Content-Length: 37
Content-Type: application/json
Connection: keep-alive
---ZHXBV3hl---H--
---ZHXBV3hl---I--
---ZHXBV3hl---J--
---ZHXBV3hl---Z--

The issue on versions 1.0.0 and 1.0.1 seems to be related to owasp-modsecurity/ModSecurity-nginx#182.

Marcello

@martinhsv
Copy link
Contributor

Can you provide more of your configuration?

  • the block that does the redirect to @403_json?
  • other blocks that have any modsecurity config?

Content from debug log could also be helpful (at level 9). One thing in particular,is that the debug log should show the parts that are configured to report (and I suspect that it is not what you think you have configured).

@cello86
Copy link
Author

cello86 commented Mar 12, 2021

This is the configuration used:

user  nobody;
pid        logs/nginx.pid;
error_log  logs/error_log info;
worker_processes auto;
thread_pool default threads=32 max_queue=65536;
thread_pool static  threads=32 max_queue=65536;

events {
    worker_connections  4096;
    use epoll;
    accept_mutex off;
}

http {

    log_format  main  '$remote_addr $remote_port $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent $request_time "$http_referer" '
                      '"$http_user_agent" "$http_cookie"';

    server_tokens off;

    upstream xxxxx  {
          keepalive 100;
          server xxxxx
    }

    server {
        server_name test.local ;
        listen 0.0.0.0:443 ssl;

        modsecurity on;
        modsecurity_rules_file /usr/local/nginx/conf/modsecurity.conf;

        access_log  syslog:server=127.0.0.1:514,facility=local4,tag=test ssl;
        error_log   syslog:server=127.0.0.1:514,facility=local5,tag=test info;

        ssl_protocols TLSv1.2
        ssl_certificate /usr/local/nginx/certs/test.local.pem;
        ssl_certificate_key /usr/local/nginx/certs/test.local.key;
        ssl_session_cache shared:SSL:10m;
        ssl_session_timeout  15m;
        ssl_prefer_server_ciphers on;
        ssl_session_tickets on;

        error_page 403 @403_json;
        error_page 404 @404_json;

        location @403_json {
            default_type application/json;
	    #issue https://github.com/SpiderLabs/ModSecurity-nginx/issues/76
	    modsecurity_rules 'SecRule REQUEST_URI "@beginsWith /" "id:1,pass,phase:2,log,ctl:ruleEngine=DetectionOnly"';
            return 403 '{"code": 403, "description": "error" } ';
        }

        location @404_json {
            default_type application/json;
	    #issue https://github.com/SpiderLabs/ModSecurity-nginx/issues/76
	    modsecurity_rules 'SecRule REQUEST_URI "@beginsWith /" "id:1,pass,phase:2,log,ctl:ruleEngine=DetectionOnly"';
            return 404 '{"code": 404, "description": "error" } ';
        }

        location ^~ /error {
	    #issue https://github.com/SpiderLabs/ModSecurity-nginx/issues/76
	    modsecurity_rules 'SecRule REQUEST_URI "@beginsWith /" "id:1,pass,phase:2,log,ctl:ruleEngine=DetectionOnly"';
            alias "/usr/local/nginx/error";
        }

        location /probe.html {
            return 200;
        }

        location ~ ^/test1/ {
            root   html;
            aio threads=default;
	    default_type application/json;
            proxy_connect_timeout 10;
            proxy_read_timeout 10;
            proxy_pass        http://xxxx;
        }

    }
}

@martinhsv
Copy link
Contributor

Thanks for the additional detail. It looks like I am able to reproduce what you have reported -- even using v3.0.4 and the current version of the connector.

I will take a closer look.

@martinhsv
Copy link
Contributor

As background, keep in mind that error redirects effectively create a second transaction. I.e. ModSecurity sees the original POST transaction and successfully parses the request body and triggers on any rules that examine these. The error redirect creates a second transaction that ModSecurity also sees.

In your configuration, when processing the second transaction (the one processed within the 404_json location block), the request body is never processed. That is why there is no section 'C' output.

I suspect that this may be expected behaviour given the way that you have configured the response to come directly from the configuration. In any case, I believe you can achieve the functionality you are looking for a couple of different ways. Perhaps the simplest is to actually create a 403.json file with your desired content, and then use configuration something like this:

error_page   403  /403.json;

location = /403.json {
    modsecurity_rules 'SecRule REQUEST_URI "@beginsWith /" "id:1,pass,phase:2,log,ctl:ruleEngine=DetectionOnly"';
    root   /usr/share/nginx/html;
}

@cello86
Copy link
Author

cello86 commented Mar 17, 2021

Hi @martinhsv,
Thanks for the tips and I configured the error page only for the 403 to file and i provide directly from the location /error. I noticed that the final configuration required on our target the propagation of the $request_id into the JSON payload. I used the sub_filter module to achieve this job and the final configuration is:

        error_page   403  /error/403.json;

        location ^~ /error {
            modsecurity_rules 'SecRule REQUEST_URI "@beginsWith /" "id:1,pass,phase:2,log,ctl:ruleEngine=DetectionOnly"';
            alias "/usr/local/nginx/error";
            sub_filter_types application/json;
            sub_filter_once off;
            sub_filter 'request_id' '$request_id';
        }

@cello86 cello86 closed this as completed Mar 19, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants