owasp-modsecurity / ModSecurity-nginx

ModSecurity v3 Nginx Connector
Apache License 2.0
1.48k stars 274 forks source link

Issue with transaction variable and chained rule #299

Closed ktptemfau closed 1 year ago

ktptemfau commented 1 year ago

Hi,

The following rules worked fine with apache/modsecurity 2.9.x to reject requests if they don't match the specified combination of HTTP method and URI

SecAction "phase:1,id:1234567,pass,setvar:TX.match="0",nolog"
SecRule REQUEST_FILENAME "^/public/post$" "phase:1,id:2,t:none,chain,nolog,setvar:TX.match="1",SkipAfter:marker"
SecRule REQUEST_METHOD "^POST$" "t:none,nolog"
#======= EOC
SecMarker marker
SecRule TX:match "0" "phase:1,id:12,log,msg:'no match',deny,status:403"

A GET request to /public/post would fail as TX.match would not be set or unset on the failing chained rule (I have no setup to play around with this combination at the moment to produce a debug log) With nginx 1.23.2 and libmodsecurity v3.2.0 requests with REQUEST_FILENAME not matching a valid URL will be rejected but testing the HTTP method is not working anymore.

...783] [] [4] Initializing transaction
...783] [] [4] Transaction context created.
...783] [] [4] Starting phase CONNECTION. (SecRules 0)
...783] [] [9] This phase consists of 1 rule(s).
...783] [] [4] Starting phase URI. (SecRules 0 + 1/2)
...783] [/public/post] [4] Starting phase REQUEST_HEADERS.  (SecRules 1)
...
...783] [/public/post] [4] (Rule: 12345699) Executing unconditional rule...
...783] [/public/post] [4] Running [independent] (non-disruptive) action: setvar
...783] [/public/post] [8] Saving variable: TX:match with value: '0'
...783] [/public/post] [9] Running action: nolog
...783] [/public/post] [4] Running (disruptive)     action: pass.
...783] [/public/post] [8] Running action pass
...783] [/public/post] [4] (Rule: 1234567) Executing operator "Rx" with param "^/public/post$" against REQUEST_FILENAME.
...783] [/public/post] [9] Target value: "/public/post" (Variable: REQUEST_FILENAME)
...783] [/public/post] [9] Matched vars updated.
...783] [/public/post] [4] Running [independent] (non-disruptive) action: setvar
...783] [/public/post] [8] Saving variable: TX:match with value: '1'
...783] [/public/post] [4] Rule returned 1.
...783] [/public/post] [4] Executing chained rule.
...783] [/public/post] [4] (Rule: 0) Executing operator "Rx" with param "^POST$" against REQUEST_METHOD.
...783] [/public/post] [9] Target value: "GET" (Variable: REQUEST_METHOD)
...783] [/public/post] [4] Rule returned 0.                            (***)
...783] [/public/post] [9] Matched vars cleaned.                       (***)
...783] [/public/post] [4] (Rule: 123456100) Executing operator "Rx" with param "0" against TX:match.
...783] [/public/post] [9] Target value: "'1'" (Variable: TX:match)    (!!!)
...783] [/public/post] [4] Rule returned 0.
...783] [/public/post] [9] Matched vars cleaned.
...
...783] [/public/post] [9] Return code `200' is not interesting to audit logs, relevant code(s): '^(?:5|4(?!04))'.

at (***) TX.match is not reset to '0' and the test at (!!!) fails and therefore the request is (erroneously) accepted.

Am I missing something on how to migrate rules from 2.x to 3.x or can I provide other details for clarification?

Thanks

ktptemfau commented 1 year ago

Sorry - I moved the question to Modsecurity as it probably does not belong here