本文主要介绍,如何通过编写规则,对提交到WEB服务器的XML格式的数据进行检测。
以WordPress历史上的一个漏洞为例:xmlrpc.php暴力破解漏洞,黑客可POST以下数据到xmlrpc.php对网站后台的账号密码进行暴力破解:
<?xml version="1.0" encoding="utf-8"?> <methodCall> <methodName>wp.getUsersBlogs</methodName> <params> <param> <value>username</value> </param> <param> <value>password</value> </param> </params> </methodCall>
本地搭建测试环境,利用以上方法进行一次攻击模拟后,通过ModSecurity的审计日志功能,可记录此次的请求数据包:
--63034d57-A-- [05/Mar/2021:16:49:05 +0800] YEHwgexiyecp5T00SgL3FwAAAIE 192.168.142.1 61967 192.168.142.131 80 --63034d57-B-- POST /wordpress/xmlrpc.php HTTP/1.1 accept: */* user-agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1) Content-Type: text/xml Host: wp.modsecurity.cn Connection: keep-alive Content-Length: 192 --63034d57-C-- <?xml version="1.0" encoding="utf-8"?><methodCall><methodName>wp.getUsersBlogs</methodName><params><param><value>admin</value></param><param><value>123456</value></param></params></methodCall>
从审计日志中可以看出,数据的确是存放在请求体当中,但如果直接通过REQUEST_BODY去检测请求体当中的数据(如下方规则),将无法匹配成功:
SecRule REQUEST_BODY "wp.getusersblogs" "phase:2,id:105,log,deny,t:lowercase"
造成无法匹配的原因是,仅当Content-Type为application/x-www-form-urlencoded,或者强制使用URLENCODED请求体解析器时,REQUEST_BODY这一变量才有效,而我们模拟攻击时提交的Content-Type为text/xml,因此REQUEST_BODY变量无效,进而导致上述规则无法起到防御作用。
针对上述原因,我们可以对规则进行改进,即当检测到Content-Type为text/xml,临时更改请求体的解析器,如下方规则所示:
SecRule REQUEST_HEADERS:Content-Type "^text/xml$" "chain,phase:2,id:106,log,t:lowercase,deny,ctl:requestBodyProcessor=XML" SecRule XML:/methodCall/methodName/text() "wp.getusersblogs" "t:lowercase"
上述规则表示,当检测到Content-Type为text/xml,临时更改请求体的解析器,同时判断/methodCall/methodName的节点数据是否为wp.getusersblogs,如果是的话,则拦截此次访问。请注意,lowercase只是将要判断的目标数据转化为小写,XML节点的名称应跟源数据保持一致,即区分大小写。
如果要判断XML数据中是否包含指定的节点,可使用以下规则:
SecRule REQUEST_HEADERS:Content-Type "^text/xml$" "chain,phase:2,id:107,log,t:lowercase,deny,ctl:requestBodyProcessor=XML" SecRule &XML:/methodCall/methodName "@gt 0"
上述规则表示,当检测到Content-Type为text/xml,临时更改请求体的解析器,同时判断methodCall节点下是否存在methodName节点,如果存在,则拦截此次访问。
版权声明
本文仅代表作者观点,不代表本站立场。
本文系作者授权发表,未经许可,不得转载。