我正在设置一个(自托管的)ghost博客,在nginx后面运行。我最近使用OWASP CRS v3规则集添加了ModSecurity v3(也就是libModSecurity)WAF,但是我在解决一些误报方面遇到了麻烦。
我的问题与this question非常相似,但建议的解决方案对我不起作用。
触发的规则是:
SecRule REQBODY_ERROR "!@eq 0" \
"id:'200002', phase:2,t:none,log,deny,status:400,msg:'Failed to parse request body.',logdata:'%{reqbody_error_msg}',severity:2"
我认为问题的原因是ghost(正确或错误)为ajax Content-Type: application/json
请求指定了GET
标头,以便将一些配置数据下载为Json。
请求被阻止,因为此Content-Type标头触发请求正文的JSON解析器:
SecRule REQUEST_HEADERS:Content-Type "application/json" \
"id:'200001',phase:1,t:none,t:lowercase,pass,nolog,ctl:requestBodyProcessor=JSON"
但是,这是一个没有请求体的GET请求,因此JSON解析器会抱怨JSON parsing error: parse error: premature EOF
...即没有要解析的Json。
尝试阅读无数指南后,来自ModSecurity documentation的Barry Pollard和许多有用的答案(例如here,here和{ {3}}),我试图编写一个特定于我的触发器场景的“白名单”规则(而不是全局禁用触发的规则)。
因此,我尝试使用以下链式规则将请求体排除在解析之外:仅针对GET
个请求,针对以/ghost/
开头的URI以及为Content-Type指定application/json
的URI。 ..
SecRule REQUEST_URI "^/ghost/" "phase:1,id:1200,t:none,t:urlDecode,t:lowercase,t:normalizePath,pass,ctl:requestBodyAccess=Off,chain"
SecRule REQUEST_METHOD "@streq get" "t:none,t:lowercase,chain"
SecRule REQUEST_HEADERS:Content-Type "application/json" "t:none,t:lowercase"
令我失望的是,这不起作用 - 我的规则在记录规则200002之前的审核日志中。换句话说,ctl:requestBodyAccess=Off
似乎不会阻止JSON解析器被触发。以下是失败事务的审计日志的相关位:
ModSecurity: Warning. Matched "Operator `Rx' with parameter `application/json' against variable `REQUEST_HEADERS:content-type' (Value: `application/json; charset=UTF-8' ) [file "/etc/nginx/modsec/modsecurity.conf"] [line "8"] [id "1200"] [rev ""] [msg ""] [data ""] [severity "0"] [ver ""] [maturity "0"] [accuracy "0"] [hostname "xxx.xxx.xxx.xxx"] [uri "/ghost/api/v0.1/configuration/"] [unique_id "152042340176.931426"] [ref "o0,7v4,30t:urlDecode,t:lowercase,t:normalizePathv0,3t:lowercaseo0,16v416,31t:lowercase"]
ModSecurity: Access denied with code 400 (phase 2). Matched "Operator `Eq' with parameter `0' against variable `REQBODY_ERROR' (Value: `1' ) [file "/etc/nginx/modsec/modsecurity.conf"] [line "51"] [id "200002"] [rev ""] [msg "Failed to parse request body."] [data "JSON parsing error: parse error: premature EOF\x0a"] [severity "2"] [ver ""] [maturity "0"] [accuracy "0"] [hostname "xxx.xxx.xxx.xxx"] [uri "/ghost/api/v0.1/configuration/"] [unique_id "152042340176.931426"] [ref "v561,1"]
FWIW,我也尝试过Barry提出的更简单的规则,用于另一个类似的问题:
SecRule REQUEST_BODY_LENGTH "@eq 0" "phase:1,id:'12345',ctl:requestBodyAccess=Off"
但这也没有什么不同。作为GET
,请求标头中没有指定Content-Length
,所以也许这就是它失败的原因?
答案 0 :(得分:0)
作为一种解决方法,我设法使用以下规则压制这种特殊的误报:
SecRule REQUEST_URI "^/ghost/" "phase:1,id:1200,t:none,t:urlDecode,t:lowercase,t:normalizePath,nolog,chain"
SecRule REQUEST_METHOD "@streq get" "t:none,t:lowercase,chain"
SecRule REQUEST_HEADERS:Content-Type "application/json" "t:none,t:lowercase, \
ctl:ruleRemoveById=200002, \
ctl:ruleRemoveById=920130"
(规则920130基本上是与SpiderLabs规则200002等效的OWASP CRS。)
然而,我需要一个规则来防止Json正文解析器错误导致拒绝这些事务似乎很愚蠢,在这种情况下防止正文解析器被调用肯定会更有效(当我决定时)? / p>
如果有人能解释如何让ctl:requestBodyAccess=Off
工作,我将不胜感激!
答案 1 :(得分:0)
你试过这个:
SecRule REQUEST_URI "^/ghost/" "phase:1,id:1200,t:none,t:urlDecode,t:lowercase,t:normalizePath,pass,ctl:requestBodyAccess=Off,chain"
SecRule REQUEST_METHOD "@streq get" "t:none,t:lowercase,chain"
SecRule REQUEST_HEADERS:Content-Type "application/json" "t:none,t:lowercase"
你能试试吗?
SecRule REQUEST_URI "^/ghost/" "phase:1,id:1200,t:none,t:urlDecode,t:lowercase,t:normalizePath,pass,chain"
SecRule REQUEST_METHOD "@streq get" "t:none,t:lowercase,chain"
SecRule REQUEST_HEADERS:Content-Type "application/json" "t:none,t:lowercase, ctl:requestBodyAccess=Off"
我认为(虽然我看到这个已经有一段时间了!),像Ctrl这样的无中断行动应该在链的末尾,而破坏性的行为(例如通行证)应该在开头。
但是我看了一会儿这么久就错了......