Description
Documentation on macro expansion says (https://github.com/SpiderLabs/ModSecurity/wiki/Reference-Manual#macro-expansion): You can use macro expansion for operators that are "compiled" such @rx, etc. however you will have some impact in efficiency.
.
In V3, macro expansion in regexes is not performed and operator "@rx ^%{var}$"
will match data against literal ^%{var}$
.
The following code can be used for demonstration:
#include "modsecurity/modsecurity.h"
#include "modsecurity/rules.h"
static void logCb(void *data, const void *ruleMessagev) {
std::cout << (char *) ruleMessagev << std::endl;
}
const char * req_uri = "/test?param=attack";
int main() {
modsecurity::ModSecurity *modsec = new modsecurity::ModSecurity();
modsecurity::Rules *rules = new modsecurity::Rules();
modsecurity::Transaction * modsecTransaction;
modsec->setServerLogCb(logCb, modsecurity::TextLogProperty);
rules->loadFromUri("test.conf");
modsecTransaction = new modsecurity::Transaction(modsec, rules, NULL);
modsecTransaction->processURI(req_uri, "GET", "1.1");
modsecTransaction->processRequestHeaders();
modsecTransaction->processRequestBody();
delete modsecTransaction;
delete rules;
delete modsec;
return 0;
}
With following test.conf
:
SecAction "id:1, nolog, setvar:tx.bad_value=attack"
SecRule ARGS:param "@rx ^%{tx.bad_value}$" id:2
It won't produce expected alert because modsec will match param
against literal ^%{tx.bad_value}$
instead of ^%attack$
.
This breaks OWASP CRS rule 920420
which uses macro expansion of variable tx.allowed_request_content_type
(this part of the rule will fire for any request because negated operator is used):
SecRule TX:0 "!^%{tx.allowed_request_content_type}$"