开源WAF规则运营入门
2023-12-25 21:20:43 Author: mp.weixin.qq.com(查看原文) 阅读量:167 收藏

虽然开源的CRS规则集[1]误报率很高,但是ModSecurity引擎还是很强大的,支持非常多的功能,包括丰富的HTTP解析后的字段。

不过虽然ModSecurity官方文档[2]中对于变量字段有说明,但是有一些细节仍然不清晰,比如 PATH_INFO变量是否经过url解码、存在参数污染时ARGS/ARGS_GET/ARGS_POST变量值是什么、为什么有时候REQUEST_BODY变量是空 等问题,不清楚这些细节容易写出存在漏报或者误报的规则。

本文介绍快速搞清变量的方法、几个重要且常用的变量。

ModSecurity支持lua插件,你可以用SecRuleScript指令和lua脚本来做一些调试。

比如添加如下规则可以打印PATH_INFO变量到终端控制台

SecRuleScript "/tmp/1.lua" "id:23333,deny"

/tmp/1.lua 内容如下

function main()
    local inspect = require("inspect")  -- inspect库需要额外安装 https://github.com/kikito/inspect.lua
    m.log(2,inspect(m.getvars("PATH_INFO")))   -- 将 PATH_INFO 变量打印到标准错误中
    return nil;
end

参数污染,简单的理解,也就是访问"http://网址/index.php?a=1&a=2&a=3",有的web容器解析请求后认为a的值是1,另一些web容器解析后认为a的值是3,这种就是存在参数污染问题。

那么ModSecurity解析参数时,会有参数污染问题吗?

结论是没有,测试过程如下

function main()
    local inspect = require("inspect")
    m.log(2,inspect(m.getvars("ARGS_GET")))
    return nil;
end

curl '127.0.0.1:8081?a=1&a=2&a=3' 后,从下面日志中可以看到,ARGS_GET会存储参数a所有的值,这是符合预期的。

127.0.0.1:8081 是我本地安装了modsecurity的apache服务

Message: { {
    name = "ARGS_GET:a",
    value = "1"
  }, {
    name = "ARGS_GET:a",
    value = "2"
  }, {
    name = "ARGS_GET:a",
    value = "3"
  } }

curl '127.0.0.1:8081?a=1&a=2&a=3' ,可以匹配到如下三条规则,也验证了 ARGS_GET 没有参数污染问题。

SecRule ARGS_GET:a "@rx 1" "id:946811,msg:'TEST1',phase:2,block,capture,severity:'CRITICAL',tag:'attack-rce',tag:'paranoia-level/1',t:none,setvar:tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}"

SecRule ARGS_GET:a "@rx 2" "id:946812,msg:'TEST2',phase:2,block,capture,severity:'CRITICAL',tag:'attack-rce',tag:'paranoia-level/1',t:none,setvar:tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}"

SecRule ARGS_GET:a "@rx 3" "id:946813,msg:'TEST3',phase:2,block,capture,severity:'CRITICAL',tag:'attack-rce',tag:'paranoia-level/1',t:none,setvar:tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}"

你觉得下面的自定义规则(禁止外部用户访问 security.xxx.com/login 接口),可以怎么绕过?

规则含义如下:

  • Host 完全匹配 security.xxx.com
  • URI 正则匹配 ^/login

上面的问题就不直接给出答案了。和路径相关的变量,你永远需要关注它有没有 url解码、../ 、./、/// 等处理逻辑:

  • /a/../b 会不会变成 /b
  • /a/./b 会不会变成 /a/b
  • ////a 会不会变成 /a

在ModSecurity中 REQUEST_URI、REQUEST_URI_RAW、PATH_INFO 三个常用的变量都和路径有关,v2版本测试结果如下

结论:

  • PATH_INFO 和 REQUEST_URI 会url解码、会处理../ 、./、///等字符
  • REQUEST_URI_RAW不做任何处理

根据文档所说,默认情况下,只有请求content-type是application/x-www-form-urlencoded时,REQUEST_BODY才会有值。

你也可以用forceRequestBodyVariable强制给REQUEST_BODY赋值,crs规则也是这么干的,如下

文档说REQUEST_BODY存储的是原始的请求body,那遇到chunked请求时,它存的是解码后还是解码前的呢?

Apache、ModSecurity-V2测试结论:是解码后的

变量的细节影响规则质量,而ModSecurity的文档并不一定准确,我们可以用lua插件打印变量来测试。

参考资料

[1]

开源的CRS规则集: https://github.com/coreruleset/coreruleset

[2]

ModSecurity官方文档: https://github.com/SpiderLabs/ModSecurity/wiki/Reference-Manual-%28v3.x%29


文章来源: https://mp.weixin.qq.com/s?__biz=MzkyMDIxMjE5MA==&mid=2247485437&idx=1&sn=cb56d7fecf40e1eb70fdeaeb02b2cc6a&chksm=c197004cf6e0895ad3c7a87db793ec9cd103c446b877a2e26bdc12b9ac794750e86e36f2163a&scene=58&subscene=0#rd
如有侵权请联系:admin#unsafe.sh