ModSecurity
ModSecurity copied to clipboard
Escape double quotation mark character in non-regex operator
Currently, am using Nginx + ModSecurity v3.
I want to create a rule that filters double quotation mark characters using a non-regex operator.
Pattern: not "redirect" to
I write the rule below:
SecRule ARGS|REQUEST_BODY "@streq not \"redirect\" to" "id:1,deny,log,..."
But it not working as I hope
Hi @capy3ra,
thanks for reporting.
After a quick scan, I can say that this is - unfortunately - a bug. But let me double check this in detail.
If you find out how to fix this or escape in another way, Ping me pls
I could review the issue in detail, and seems like this is an old and already reported bug - see #2148.
I discovered this unexpected behavior more than 5 years ago, but the problem is in the engine's parser, which is very sensitive and critical area. There I explained the root cause of the problem and there is a solution - put the rule in the web server's config not to an included file, eg in nginx.conf:
modsecurity_rules '
SecRule ARGS|REQUEST_BODY "@streq not \"redirect\" to" "id:1,deny,log,..."
';
(and please do not forget to add a phase action to the rule :smiley:).
More explanation - here is how looks like the operand (not \"redirect\" to) and the target (ARGS - namely not "redirect" to) in gdb:
Breakpoint 1, modsecurity::operators::StrEq::evaluate (this=0x560536130e00, transaction=0x5605360bb520, str="not \"redirect\" to") at operators/str_eq.cc:25
25 return !pt.compare(str);
(gdb) p pt
$1 = "not \\\"redirect\\\" to"
(gdb) p str
$2 = "not \"redirect\" to"
As you can see, the engine do not strips the \ (backslash) characters. There are 3 \ because there is one which is escaped and the " is escaped too. It's easy to see that the two string won't match.
It seems that a solution to this problem should be taken...
Your solution not work with me. I tried:
modsecurity on;
modsecurity_rules_file /usr/nginx/conf/rules/main.conf;
modsecurity_rules '
SecRule ARGS "@streq not \"redirect\" to" "id:1,deny,log,phase:1"
';
And error log returned:
2024/09/13 16:23:13 [emerg] 4192728#0: "modsecurity_rules" directive Rules error. File: <<reference missing or not informed>>. Line: 2. Column: 65. Expecting an action, got: to" "id:1,deny,log,phase:1" in /usr/nginx/conf/modules/modsecurity.conf:7
Ah, sorry - you are right. Unfortunately the parser does not allow this syntax. You still need to add double escape in this case, like:
modsecurity_rules '
SecRule ARGS "@streq not \\"redirect\\" to" "id:1,deny,log,phase:1"
';
A possible bypass is that you use a trick: put a transformation and the transformed pattern, like:
SecRule ARGS "@streq not+%5c%22redirect%5c%22+to" \
"id:1,\
phase:2,\
t:none,t:urlEncode,\
deny,\
log"
but you have to inspect possible security reasons, eg. double encoded argument...