免责声明:由于传播、利用本公众号所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,公众号及作者不为此承担任何责任,一旦造成后果请自行承担!如有侵权烦请告知,我们会立即删除并致歉。谢谢!
文章作者:先知社区(doggy)
文章来源:https://xz.aliyun.com/news/294
介绍
编码问题一直以来是WAF防御体系中的薄弱环节,由于HTTP(S)协议支持多种格式数据传输,当网站存在SQL注入漏洞时,黑客往往会利用编码绕过WAF的防御。本文将简单介绍利用Fuzz技术探测对于json格式编码的数据中一些特殊字符的编码规律,提高WAF对于json格式数据的兼容性。
为了便于理解,我们先来看一个在URL中进行SQL注入的例子。
假设服务器上的article.php是这样一段代码:
<?php
$id=$_GET['id'];
$sql="select * from article where id=$id";
mysql_query($sql,$conn);
?>
那么当我们请求 article.php?id=1 and 1=1 时,mysql会执行
select * from article where id=1 and 1=1
这样就可以通过修改and后面的语句进行查询,最终甚至可以拖下整个数据库数据。WAF(Web Application Firewall),中文名称网站应用防火墙,可以对用户提交的请求进行判断,拦截并阻断恶意的HTTP(S)请求,以达到保护网站安全的目的。对于部署了WAF的网站我们可以通过匹配关键字来阻断攻击。例如检测到HTTP(S)请求中含有and 1=1,我们可以将该请求阻断,当然这里仅仅是举个例子,真实情况下需要阻断请求的规则匹配十分复杂。黑客可以通过变形:”and/**/1=1”、”and%0a1=1”、”and+1=1”来绕过防御,这时就要求WAF能够加载这些变形的规则将有可能绕过WAF的请求全部拦截。
在json格式的数据中,由于服务器会对json数据进行一次json解析,导致有些字符可能会漏防,所以本文主要研究有哪些字符在php+mysql执行环境中的json格式解码后容易出现遗漏。
这张图描述了json格式传输的数据会被转义的几种情况,例如”会被转义成”,会被转义成,n会被转义成换行,u(四位十六进制字符)会被转义成unicode解码后对应的字符。
测试环境:php5.4.39 mysql 5.1.73。
测试用例: 这里我们使用开源系统phpaacms中的show.php ,修改php标签内的内容为:
<?php
include_once 'global.php';
$id = json_decode($_GET['id'])->id;
for($i = 0; $i < strlen($id); $i ++)
{
printf("%x",ord($id[$i]));
echo ",";
}
$arc = getArticleInfo($id);
?>
测试URL:
http://127.0.0.1/phpaacms/show.php?id={"id":"31 and 1=1"}
测试说明:这里以n为例,我们跟踪一下从提交请求到mysql后端的执行流程。
http://127.0.0.1/phpaacms/show.php?id={"id":"31 andn1=1"}
这里的换行符对于mysql语句来说仅仅是and和1=1之间的分隔符,对于执行没有影响。可见在json环境下传入的n 字符会带入到mysql执行。
0x01 URL编码探测
由于-%FF是经过url编码后的字符,对于%09、%0A、%0B、%0C、%0D这些字符都是在普通url中绕过waf常见的单词分隔符,所以我们想看一下这些特殊字符在json格式下是否能够被正常解析。
利用工具:Burpsuite 中的Intruder模块。该模块可以通过加载字典将http请求包指定位置的内容进行替换,从而实现类似“暴力破解”的效果。
测试用例:
http://127.0.0.1/phpaacms/show.php?id={"id":"31 and%(00-FF)1=1"}
我们这里将url中 and与1=1之间的空格依次替换为~%FF。
测试结果:
测试结果中,我们可以看出不同的payload发送的请求http响应也不同,我们可以依据长度(Length)来进行筛选,按长度排序以后,返回长度2743的为”and 1=1”执行成功的请求,也就是说sql注入可以执行,而返回长度2664或小于2664的payload说明无法sql注入成功,这里我们看到仅有%20(space)和%2B(+) 可以在json格式中存活,在常见注入的url中的%0A %0B……这些字符并不能被php的json_decode所解析。
0x02转义探测
这一次我们想探测经过’’转义过的字符是否会被json decode并在mysql中执行。
测试用例:
http://127.0.0.1/phpaacms/show.php?id={"id":"31 and%(00-FF)1=1"}
%66(f)、%6E(n)、 %72(r)、%74(t)。也就是说 f n r t 这四个字符经过json_decode后,可以被当作mysql分隔符进行解析。
测试用例:
http://127.0.0.1/phpaacms/show.php?id={"id":"31 andu00(00-FF)1=1"}
这一次主要测试u0000-u00ff 经过unicode编码的类型是否能够通过json_decode。
测试结果:
可以看出,u0009、u000A、u000B、u000C、u000D、u0020、u002B均可以被json_decode并带入mysql作为mysql单词分隔符。
0x03单词中的探测
为了探测x这类字符是否会被json_decode解析后替换为空,这里我们采用单词间的探测,即在mysql单词中插入该用例进行探测这里采用的是”anxd”。
测试用例:
http://127.0.0.1/phpaacms/show.php?id={"id":"31 an%(00-FF)d 1=1"}
测试结果:
无一幸免,可见在单词中插入这些转义字符并不会在json解析的时候丢失,多于的转义字符是破坏mysql语法的。
0x04十六进制探测
对于常用的十六进制编码,有可能会采用 0-ff和x00-xff。两种形式,这里我们分别fuzz一下。
1) 0-FF
测试用例:
http://127.0.0.1/phpaacms/show.php?id={"id":"31 and(00-FF) 1=1"}
测试结果:
可见 0-FF 并不能如我们所愿被当作-%FF之类的解析。
2) x00-xFF
测试用例:
http://127.0.0.1/phpaacms/show.php?id={"id":"31 andx(00-FF)1=1"}
测试结果:
可以看出,x00-FF与 0-FF一样都不能被json直接解析。
0x05 小结
经过以上几次fuzz,可以看出在json环境下:
%20 %2B f n r t u0009 u000A u000B u000C u000D u0020 u002B
这些字符会作为mysql分隔符。下面我们来进行实战。
0x06 实战
经过对目前国内主流的几大WAF产品测试,我们目前还没有发现能够防御该漏洞的产品。
以国内某知名云安全厂商的waf产品为例:
正常情况下:
我们请求 http://www.xx.com/xx?id=1 会下图:
1)使用url编码用例进行探测
测试结果:
可以发现对于%20进行了防护,而对于%2b没有防护。
2)使用f n r t编码用例进行探测
使用r f n t 测试结果均没有防护:
3)使用/**/代替注释符进行探测
正常情况下,对于json格式数据的注入我们可以类似这样构造:
http://www.xx.com/xx?id={%22id%22:%221%20and/**/1=1%22}
对于常用的绕过waf手段:替换空格为/**/,可能大多数网站都会有所防范。
但是对于 json格式来说// 同样可以decode成为 //带入mysql成为分隔符。
http://www.xx.com/xx?id={%22id%22:%221%20and/**/1=1%22}
0x07总结
在waf对抗技术中,针对编码(json、base64……)中的特殊字符处理上仍然是受到挑战的风险点,在设计和完善waf产品时应当充分考虑业务系统的数据交互流程,从而进一步将黑客对于漏洞的恶意利用遏制在萌芽中。
推 荐 阅 读
横向移动之RDP&Desktop Session Hija
原文始发于微信公众号(七芒星实验室):浅谈json参数解析对waf绕过的影响
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论