长亭百川云 - 文章详情

开源WAF规则运营入门

leveryd

78

2024-07-13

背景

虽然开源的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

ARGS_GET 和 参数污染

参数污染,简单的理解,也就是访问"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}"

PATH_INFO 是否经过url解码等处理?

你觉得下面的自定义规则(禁止外部用户访问 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不做任何处理

REQUEST_BODY

根据文档所说,默认情况下,只有请求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

相关推荐
关注或联系我们
添加百川云公众号,移动管理云安全产品
咨询热线:
4000-327-707
百川公众号
百川公众号
百川云客服
百川云客服

Copyright ©2024 北京长亭科技有限公司
icon
京ICP备 2024055124号-2