我想匹配 ModSecurity 中名为 usr/bin/ 的参数。
我测试了以下规则并确认它匹配(假定参数的值为 abc):
SecRule ARGS:/usr\/bin\// "@streq abc" "id:123,status:400,deny"
据我了解,这是有效的,因为在将模式输入正则表达式引擎之前,\ 被简化为 \ (我认为这只是 C/C++ 的一个功能,PHP 的行为方式相同)。然后,正则表达式引擎将 \ 解释为单个 ,进而转义下面的 /,因此不会发生未转义的分隔符错误。
如果是这种情况,我希望以下规则也匹配:
SecRule ARGS:/usr\/bin\// "@streq abc" "id:123,status:400,deny"
但我的测试结论是事实并非如此。为什么第二条规则也不匹配?我对反斜杠处理方式的理解是否正确?
据我了解,这是有效的,因为在将模式输入到正则表达式引擎之前,\ 被简化为 \ (我认为这只是 C/C++ 的一个功能,PHP 的行为方式相同)。
不,这是一个引擎(ModSecurity)功能。请查看文档:
有时您需要查看一组参数,每个参数的名称都略有不同。在这种情况下,您可以在选择运算符本身中指定正则表达式。以下规则将查找名称以 id 开头的所有参数:
SecRule ARGS:/^id_/ dirty "id:11"
因此,
/.../
符号用于表示集合中的正则表达式。
如果是这种情况,我希望以下规则也匹配:
SecRule ARGS:/usr\\/bin\\// "@streq abc" "id:123,status:400,deny"
但我的测试结论是事实并非如此。为什么第二条规则也不匹配?我对反斜杠处理方式的理解是否正确?
请再次检查您的结果和其他设置。这条规则对我有用。我在我的测试环境中设置了这个规则,并尝试了一下:
$ curl -v -X POST -d "usr/bin/=abc" "http://localhost"
...
< HTTP/1.1 400 Bad Request
< Date: Mon, 16 Oct 2023 07:38:17 GMT
< Server: Apache/2.4.56 (Debian)
< Content-Length: 301
< Connection: close
< Content-Type: text/html; charset=iso-8859-1
<
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>400 Bad Request</title>
...
在我的日志中有这些行:
错误日志:
[client ::1:40376] [client ::1] ModSecurity: Access denied with code 400 (phase 2). String match "abc" at ARGS:usr/bin/....
在调试日志中:
Rule 7f9f36829440: SecRule "ARGS:/usr\\/bin\\//" "@streq abc" "phase:2,log,auditlog,id:123,status:400,deny"
Transformation completed in 0 usec.
Executing operator "streq" with param "abc" against ARGS:usr/bin/.
Target value: "abc"
Operator completed in 0 usec.
Rule returned 1.
所以我认为你的规则符合你的期望。
我也尝试了这个请求的规则:
curl -v -X POST -d "usr/bin/less=abc" "http://localhost"
这也有效。