ModSecurity:按值列出白名单参数

ModSecurity: Whitelist Arguments By Value

我正在尝试为具有未知名称但匹配值的参数设置 ModSecurity 白名单。例如,我想将任何时间戳参数列入白名单(例如 timestamp=2016-01-01 00:00:00)。目前,这会触发规则 981173 (Restricted SQL Character Anomaly Detection Alert - Total # of special characters exceeded)

以下将起作用,但如果至少有一个匹配,将跳过对所有参数的检查,因此它不会捕获 https://www.example.com/?timestamp=2016-01-01+00:00:00&badvalue=2016-01-01+00:00:00:00.

中的 badvalue 参数
SecRule ARGS "@rx ^2[0-9]{3}-[0-1][0-9]-[0-3][0-9] [0-2][0-9]:[0-5][0-9]:[0-5][0-9]$" \
    "id:'99001', phase:1, nolog, pass, t:none, \
    ctl:ruleRemoveTargetByTag=OWASP_CRS/WEB_ATTACK/SQL_INJECTION;ARGS"

如果我对参数名称进行硬编码,则以下内容有效。

SecRule ARGS:timestamp "@rx ^2[0-9]{3}-[0-1][0-9]-[0-3][0-9] [0-2][0-9]:[0-5][0-9]:[0-5][0-9]$" \
    "id:'99001', phase:1, nolog, pass, t:none, \
    ctl:ruleRemoveTargetByTag=OWASP_CRS/WEB_ATTACK/SQL_INJECTION;ARGS:timestamp"

我尝试了以下方法,但没有用。

SecRule ARGS "@rx ^2[0-9]{3}-[0-1][0-9]-[0-3][0-9] [0-2][0-9]:[0-5][0-9]:[0-5][0-9]$" \
    "id:'99001', phase:1, nolog, pass, t:none, \
    ctl:ruleRemoveTargetByTag=OWASP_CRS/WEB_ATTACK/SQL_INJECTION;/%{MATCHED_VAR_NAME}/"

SecRule ARGS "@rx ^2[0-9]{3}-[0-1][0-9]-[0-3][0-9] [0-2][0-9]:[0-5][0-9]:[0-5][0-9]$" \
    "id:'99001', phase:1, nolog, pass, t:none, \
    ctl:ruleRemoveTargetByTag=OWASP_CRS/WEB_ATTACK/SQL_INJECTION;MATCHED_VAR_NAME"

这可以用 ModSecurity 实现吗?有没有办法在这个用例中使用 MATCHED_VAR_NAME ?我宁愿不必为每个可能包含时间戳的参数名称添加规则。

遗憾的是,目前无法在 ctl 动作参数中使用宏扩展。

作为证据考虑以下示例:

SecRule ARGS "@contains bob" "id:1,t:none,pass,ctl:ruleRemoveTargetById=2;ARGS:x"
SecRule ARGS "@contains hello" "id:2,deny,status:403"

当提供以下请求时:'http://localhost/?x=bobhello' 我们将在评估第二条规则时在调试日志中看到以下内容

[04/Aug/2016:00:44:07 --0400] [localhost/sid#55e47aa583e0][rid#55e47ad7cb10][/][4] Recipe: Invoking rule 55e47ab14638; [file "/etc/httpd/modsecurity.d/includeOWASP.conf"] [line "12"] [id "2"]. [04/Aug/2016:00:44:07 --0400] [localhost/sid#55e47aa583e0][rid#55e47ad7cb10][/][5] Rule 55e47ab14638: SecRule "ARGS" "@contains hello" "phase:2,log,auditlog,id:2,deny,status:403" [04/Aug/2016:00:44:07 --0400] [localhost/sid#55e47aa583e0][rid#55e47ad7cb10][/][4] Transformation completed in 0 usec. [04/Aug/2016:00:44:07 --0400] [localhost/sid#55e47aa583e0][rid#55e47ad7cb10][/][9] fetch_target_exception: Found exception target list [ARGS:x] for rule id 2 [04/Aug/2016:00:44:07 --0400] [localhost/sid#55e47aa583e0][rid#55e47ad7cb10][/][9] fetch_target_exception: Target ARGS:x will not be processed. [04/Aug/2016:00:44:07 --0400] [localhost/sid#55e47aa583e0][rid#55e47ad7cb10][/][4] Executing operator "contains" with param "hello" against ARGS:x skipped. [04/Aug/2016:00:44:07 --0400] [localhost/sid#55e47aa583e0][rid#55e47ad7cb10][/][4] Rule returned 0.

但是,当我们提供相同的请求('http://localhost/?x=bobhello')时,我们的 ctl 操作中有宏扩展(如下所示):

SecRule ARGS "@contains bob" "id:1,t:none,pass,ctl:ruleRemoveTargetById=2;%{MATCHED_VAR_NAME}"
SecRule ARGS "@contains hello" "id:2,deny,status:403"

我们的Debug日志会出现如下:

[04/Aug/2016:00:44:41 --0400] [localhost/sid#559f82a0b3e0][rid#559f82d2fb50][/][5] Rule 559f82ac76e8: SecRule "ARGS" "@contains hello" "phase:2,log,auditlog,id:2,deny,status:403" [04/Aug/2016:00:44:41 --0400] [localhost/sid#559f82a0b3e0][rid#559f82d2fb50][/][4] Transformation completed in 0 usec. [04/Aug/2016:00:44:41 --0400] [localhost/sid#559f82a0b3e0][rid#559f82d2fb50][/][9] fetch_target_exception: Found exception target list [%{MATCHED_VAR_NAME}] for rule id 2 [04/Aug/2016:00:44:41 --0400] [localhost/sid#559f82a0b3e0][rid#559f82d2fb50][/][4] Executing operator "contains" with param "hello" against ARGS:x. [04/Aug/2016:00:44:41 --0400] [localhost/sid#559f82a0b3e0][rid#559f82d2fb50][/][9] Target value: "bobhello" [04/Aug/2016:00:44:41 --0400] [localhost/sid#559f82a0b3e0][rid#559f82d2fb50][/][4] Operator completed in 2 usec. [04/Aug/2016:00:44:41 --0400] [localhost/sid#559f82a0b3e0][rid#559f82d2fb50][/][4] Rule returned 1.

我想不出一种无需过多开销即可实现此目标的方法。此时最好的解决方案可能是手动将每个有问题的参数列入白名单。