-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Description
In version 3 of libmodsec, some variables that according to the documentation should be 'collections' are treated as scalars. This affects the following variables:
ARGS_NAMES
ARGS_GET_NAMES
ARGS_POST_NAMES
REQUEST_HEADERS_NAMES
RESPONSE_HEADERS_NAMES
In the code these are implemented as instances of class AnchoredVariable. These variables are constructed from the individual args (or headers) by concatenation (with a single whitespace as the separator).
A rule like the following (from https://github.com/SpiderLabs/ModSecurity/wiki/Reference-Manual#ARGS_NAMES) therefore doesn't work as intended:
SecRule ARGS_NAMES "!^(p|a)$" "id:13"
Instead of rejecting all requests that contain an argument other than 'p' and 'a', it rejects all requests that have more than one argument (and the one argument has to be called either 'a' or 'p'). For a query string 'a=v1&p=v2', the match will be made against the string
'a p'. This won't match the regex '^(p|a)$' and the request will be rejected.
Similarly, the following rule from version 3.0.2 of the CRS doesn't work because it rejects all requests that have more than one argument:
SecRule ARGS|ARGS_NAMES|REQUEST_BODY "@validateByteRange
38,44-46,48-58,61,65-90,95,97-122"
"phase:request,
rev:'2',
ver:'OWASP_CRS/3.0.0',
maturity:'9',
accuracy:'9',
block,
msg:'Invalid character in request (outside of very strict set)',
id:920273,
severity:'CRITICAL',
t:none,t:urlDecodeUni,
tag:'application-multi',
tag:'language-multi',
tag:'platform-multi',
tag:'attack-protocol',
tag:'OWASP_CRS/PROTOCOL_VIOLATION/EVASION',
tag:'paranoia-level/4',
setvar:'tx.msg=%{rule.msg}',
setvar:tx.anomaly_score=+%{tx.critical_anomaly_score},
setvar:tx.%{rule.id
}-OWASP_CRS/PROTOCOL_VIOLATION/EVASION-%{matched_var_name}=%{matched_var}"
Interestingly, this seems to be entirely intentional in the code: there are even tests for exactly this behaviour: In file 'variable-ARGS_NAMES', a request with 'param1=value1¶m2=value2' and a rule
SecRule ARGS_NAMES "@contains test " "id:1,phase:3,pass,t:trim"
is expected to produce the following debug log line:
Target value: "param1 param2"
Of all the variables ending in '_NAMES', only REQUEST_COOKIES_NAMES is actually treated as a collection.