Skip to content

ModSecurity False Positive with respect to logging in ModSec audit + NGX error logs due to NGINX behavior with error_page directive #182

Open
@jeremyjpj0916

Description

@jeremyjpj0916

Decided to pull out my comment to a separate issue since its unrelated to the other issue I raised originally:

I was trying to limit the relevant to 400's and 403's for capturing blocked transactions by ModSecurity:

SecAuditLogRelevantStatus "^(?:4((00)|(03)))"

Yet I see the audit log in RelevantOnly mode still also capturing 504 status messages as well for some reason.

SO this one is an interesting case. I am 100% sure on why 504's were making it into the audit logs even through its regex was set to 400's and 403's because I saw odd behavior in other apps too that hook into NGX with logged values not matching what the client really sent.

Firstly take a gander here(the app we run on nginx + openresty), leveraging the error_page directive:
https://github.com/Kong/kong/blob/3.7.0/kong/templates/nginx_kong.lua#L94

Then take a gander here at how Kong or OpenResty can be patched for such situations:
Kong/kong#5073
openresty/openresty#396

So what happens is when NGINX does an internal redirect via error_page, and the CTX of the client HTTP METHOD gets reset to GET always, so the NGINX ModSec audit/error logs are thinking REAL 504 timeout transactions are now a GET with a HTTP body(client sends req body) in the audit log logic(The Method the client actually used in the originating request was a POST), so it saves an blocked error log w 403 in the audit log file section H, for the transaction BUT the real transaction was a 504 and it was presented to the client as a 504, just internal logging and record keeping Modsecurity-nginx is not handling these scenarios where error_page directive gets used by folks leveraging the NGINX web server.

The fix could easily be if yall added a custom mod security http method variable to the tx context in the pre-access phase taking the original r->method to track the Method before the error_page directive internal redirect and read that custom mod sec http method variable after in the audit/error log phase logic after the redirect has occurred as the source of truth rather than the current ngx contexts r->method(which would be reset to always be GET at that time). Will save on the noisy invalid logs.

Ex of current behavior(Upstream times out in reverse proxy call, we hit error_page directive, http method gets reset to GET internally, triggering ModSec to log this tx as a block in error + audit log incorrectly when it was really just a harmless timeout):

2020/02/20 07:47:40 [error] 71#0: *65758 upstream timed out (110: Operation timed out) while connecting to upstream, client: 10.96.16.138, server: kong, request: "POST /api/memleak HTTP/1.1", upstream: "http://10.86.228.171:9393/ ", host: "gateway.company.com"

2020/02/20 07:47:40 [error] 71#0: *65758 [client 10.96.16.138] ModSecurity: Access denied with code 403 (phase 2). Matched "Operator Ge' with parameter 5' against variable TX:ANOMALY_SCORE' (Value: 5' ) [file "/usr/local/owasp-modsecurity-crs-3.2.0/rules/REQUEST-949-BLOCKING-EVALUATION.conf"] [line "79"] [id "949110"] [rev ""] [msg "Inbound Anomaly Score Exceeded (Total Score: 5)"] [data ""] [severity "2"] [ver ""] [maturity "0"] [accuracy "0"] [tag "application-multi"] [tag "language-multi"] [tag "platform-multi"] [tag "attack-generic"] [hostname "10.129.45.91"] [uri "/api/memleak"] [unique_id "158218486097.459274"] ...

ModSecurity-nginx: latest master branch

Metadata

Metadata

Assignees

No one assigned

    Labels

    nostaleThe label to apply when an issue is exempt from being marked stale

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions