4. Fuzz方法

4.1. 简介

Fuzz又称模糊测试,是一种侧重于发现软件安全漏洞的方法。典型的Fuzz测试过程是通过自动的或半自动的方法,反复驱动目标软件运行,并为其提供特别构造的输入数据,同时监控软件运行的异常,进而根据异常结果及输入数据查找软件的安全漏洞。谷歌、微软、思科等公司都使用模糊测试作为软件安全开发流程的一部分。

4.2. 白盒Fuzz

4.2.1. 简介

白盒Fuzz在测试之前通常会先对应用进行分析,获取一定的信息来辅助其创建的输入能在应用程序中发现崩溃。

其通常遇到的问题是一个应用程序一般有有许多分支,然后形成许多可能的执行流。不过如果有了很大的测试空间,就有可能创建几乎无限的输入来遍历所有的执行流。一般白盒Fuzz会试图创造在更少的输入的同时来尽量覆盖更多的路径。目前也有一些研究取得了成果,比如CRAX[1-2]就用符号执行的方式完成了一个白盒浏览器漏洞Fuzz工具。

但是由于执行流程过多和复杂的约束,白盒Fuzz在应用程序中可能并不精确。 此外,白盒Fuzz分析应用程序需要比较多的时间,所以浏览器Fuzz一般仍以黑盒Fuzz为主。

4.2.2. 符号执行

符号执行是白盒Fuzz的一个常用技术。其关键思想就是,把输入变为符号值,那么程序计算的输出值就是一个符号输入值的函数。这个符号化的过程在文章[1-9]中已有简要阐述,简而言之,就是一个程序执行的路径通常是true和false条件的序列,这些条件是在分支语句处产生的。

符号执行要解决的问题主要是路径选择、约束求解、内存建模、处理并发这几个方面。

4.3. 黑盒Fuzz

黑盒Fuzz是一个有效和找到漏洞的简单方法,和白盒不同的是,黑盒Fuzz不关心程序执行的状态,认为程序是一个黑盒。其直接产生输入然后尝试找到结果。黑盒Fuzz也常被称为是数据驱动的Fuzz,大部分传统Fuzzer都是黑盒的。

4.4. 灰盒Fuzz

在白盒和黑盒之后,一些研究者提出了灰盒Fuzz,结合黑盒和白盒两种方式进行Fuzz。使用黑盒Fuzz进行执行,也一定程度上使用轻量的白盒方式为黑盒提供反馈。比单纯的白盒Fuzz更轻量级,比黑盒Fuzz更有效率。

4.5. 生成策略

4.5.1. Mutation-Based Fuzz

在Mutation-Based Fuzz中,一般会提供一个到多个有效的样本,基于变异Fuzz方式对这些样本进行变异。常用的方式有字节级跳变、块级别的替换、删除、增加、重复、基于字典的变异等。

对浏览器的模糊测试而言,为了达到更好的效果,目前的变异方式有基于源代码的变异、基于AST的变异、基于字节码的变异等。

相对来说,这种Fuzz方式比较好实现,而且几乎不需要任何的先验知识,只要有一个或几个构造好的样本即可。但是相对来说,这种Fuzz方式也更依赖于给定的样本,如果样本触发的代码覆盖率不高,那么这种方式的覆盖率一般也不会高。

4.5.2. Genertion-Based Fuzz

Genertion-Based Fuzz通常使用的方法有基于随机字符的生成、基于语法结构的生成等。相对Mutation-Based Fuzz,直接生成样本的方式覆盖率会更高。但是相对的,这种方式也需要更多的种子样本,对样本的依赖性也更强。

4.5.3. Hybrid Fuzz

考虑到Genertion-Based和Mutation-Based的优缺点,那么另一种方式就是结合两种模式共同进行Fuzz,生成随机样本之后再进行相应的变换,以获得更好的Fuzz效率。

4.6. 导向策略

4.6.1. 覆盖率导向

在生成或变异的过程中,为了能更有效的Fuzz,通常会使用导向性的策略,比如基于覆盖率的导向性策略等。

导向性Fuzz最开始由AFL提出,其对样本执行后的覆盖率进行统计,找到变异后对覆盖率影响较大的字节,更多的对其进行测试,来实现更高效的变异。

而后逐渐引入了基于机器学习的方式,比如基于随机下降算法的覆盖率导向方式、基于进化算法的覆盖率导向方式等来实现更高效的导向。

4.6.2. Patch Based

除了覆盖率导向,也有基于补丁分析的模糊测试方式。