arXiv:1812.00140 (cs) The Art, Science, and Engineering of Fuzzing: A Survey的阅读感想与过程中遇到的问题
我太菜了,一篇论文读了两个星期,真的好多不会的,要加紧学习了
目标论文大致内容
文章将现有的模糊测试的研究进行了总结,并对现有的杂乱无章的模糊测试相关术语提出了一个统一的命名。
还根据对模糊测试的过程的拆分,对现有的模糊测试研究(包括论文以及GitHub上的项目)进行了分类汇总。
将模糊测试出现以来的大部分重要论文进行了归类。
模糊测试过程
这一部分正好在我这篇文章的过程中,文明老师讲过一遍了…节约大量时间
相关的论文内容已经做好分类了,我也不在这里说了,直接上一个链接吧,在第八页有,以后有时间可以读读
【腾讯文档】模糊测试技术进展报告_文明 https://docs.qq.com/slide/DSVZNY3p0am13RE1V
预处理器(Processor)
主要进行两件事,程序插装、选择初始种子
程序插桩
- 分为动态插装 和 静态插装
- 可以对程序的分支进行插装,记录分支的覆盖情况。但是同时有些技术会引起路径冲突,CollAFL [S&P 2018] 提出路径敏感的哈希方法,来记录路径覆盖信息,如此可以解决路径冲突的问题
- 还可以通过对程序的指定的关键信息进行插装,进行定向模糊测试
选择初始种子(Seed Selection)
通过一些算法去尽可能减小初始种子池(seed pool),选择最大覆盖率的最小种子集。
种子修剪(Seed Trimming)
更小的种子可能会有更小的内存消耗,产生更加全面的效果。所以有些Fuzzer会选择调高小种子的优先级。
准备驱动程序(Preparing a Driver Application)
要让Fuzzer能够成功调用PUT,需要在开始之前自己手写一个驱动。
调度器(Scheduler)
Fuzz Configuration Scheduling(FCS) Algorithm: 在此区分黑灰白盒,
在模糊测试中,调度指选择一组合适的测试参数来开展下一轮测试迭代。BFF
和AFLFast
成功的关键在于他们创新的调度算法。
模糊测试中,动态的添加与删除种子库中的种子,是探索程序不同状态,以保障测试有效性的关键。
种子生成器(Input Generator)
随机生成(Random-based Generator)
随机生成字符串、数字,进行测试,这样具有一定的盲目性,比较难获得有效的结果
基于模型生成(Model-based Generator)
- 基于语法生成:Zest [ISSTA 2019] 生成满足语法语义的JavaScript/XML
- 基于协议生成:T-Fuzz [ICST 2014] 生成满足网络协议的输入
- 基于预定义模型:内核模糊测试通常以系统调用模板的形式定义输入模型,例如参数数量与类型
- 基于编码模型:当检测某些类型文件的解码器的时候,可以通过稍稍变异已有的编码器来生成变异输出
基于变异生成(Mutation-based Generator)
- 比特翻转:直接翻转固定数量的比特 AFL/HongGFuzz/SymFuzz[S&P 2015]
- 算数变异:将选定的字节序列视为整数,然后对该值执行简单的算术运算
- 基于块的变异:块,指二进制种子的一个序列。通过对块的增删位移进行变异。
- 基于字典的变异:定义一组可能具有语义意义的预定义值用于变异LibFuzzer
种子评价器(Input Evaluator)
判断种子是否触发漏洞
这里用到了Bug Oracle的概念,把违反安全规定的行为定义为,程序因为一个危险信号而终止。
需要注意的是,bug与crash不是一一对应的关系,有的bug可能不会产生crash,有的bug代码可能离crash处很远,有的不同的bug可能产生相同的crash,这都是可能造成判定种子的失误。可能出现的crash类型大致有以下
内存与类型安全 Memory and Type Safety
- 空间上的内存安全错误——在指针的作用域外取消了指针的指向
- 时间上的内存安全错误——在指针已经失效后重新引用指针
未定义行为 Undefined Behaviors
输入验证漏洞 Input Validation
语义差异漏洞 Sematic Difference
分流 Triage
这个词我也不知道怎么翻译,就先这样写着吧,Triage是指分析以及上报违反安全规则的行为的测试用例的过程。
大致分为以下几步
重复数据删除 Deduplication
重复数据删除是要从结果集合中,剔除掉那些因为同一个bug引起的问题
重复数据删除通常有以下几种方法
堆栈回溯哈希 Stack Back-trace Hashing
在PUT崩溃时,进行堆栈的回溯,给回溯的内容分配一个哈希值。不过因为这种方法唯一标记的是崩溃信息,在原理上有些问题,无法保证相同的崩溃一定是由相同的bug产生的
基于覆盖的重复数据删除
最常见的是用于AFL中,AFL是一个灰盒的Fuzzer,判定规则如下
- 当崩溃覆盖了一个之前从未发现的内容
- 当本次崩溃并未完全覆盖之前所有的崩溃的交集的时候
语义感知的重复数据删除
优先级与可利用性确定 Prioritization and Exploitability
优先级就是指显示给用户的优先级,这取决于发现的bug的严重性和独特性。当bug严重且容易被利用的时候,攻击者很容易就会从这方面下手,所以要优先处理这一类的bug。
测试用例规模最小化 Test case minization
识别出违规用例中最小的一个子集,保证这个子集能够触发所有的违规。有时还可以去主动制作一个更小更简单但是依然能导致违规的测试用例。
更新器(Updater)
更新器一般是用于更新种子池 以及 模糊测试配置的
更新种子池 Seed Pool Update
- 基于遗传算法的更新:基于启发式的方法,模仿生物学进化机制,对种子进行变异,重组和选择
- 基于统计模型的更新:从历史数据中学习有效模型,来指导种子池的更新
- 基于复杂程序语义的更新:判断是否覆盖了复杂分支?定向模糊测试
维护最小集合 Maintaining a Minset
- 在最大化目标(分支覆盖率)的情况下,维护最少数量的测试参数
模糊测试分类
黑盒
- 无法访问PUT的内部,无法获取PUT内部与运行相关的任何数据
- 仅能观测PUT的输入与输出
灰盒
- 能观测PUT中的部分信息,可以利用简单的静态分析技术,来记录动态执行信息,例如程序的覆盖率信息
- 之前遇到的代码插桩的事情,可能就是与这个有点关系
白盒
- 能够全面的系统的访问PUT的内部状态
- 通常能够结合动态符号执行以及污点分析等技术进行模糊测试
模糊测试名词解释
PUT
Program Under Test 指被测试的程序
Fuzzing
是指PUT从模糊测试的 input space 中执行一个 input,需要注意的是:
- 模糊测试的输入不必要包含程序所有预期输入,只要有包含一个不在程序预期输入中的input就行
- 通常情况下,一般会进行多轮迭代,需要精心设计迭代内容
Fuzz Testing
使用Fuzzing技术去测试PUT是否触发了一个安全策略
Fuzzer
对PUT进行模糊测试的工具
Fuzz Campaign
针对某一个安全规则,使用一组特定input数据的一次PUT执行
Bug Oracle
判定一次执行的结果是否触发了PUT的一种安全策略
Fuzz Configuration
应用于Fuzz的算法的一组参数,比如种子输入、已发现的不同的bug树、程序的覆盖率、测试已经执行的时间
遇到的问题黑洞
符号执行
污点分析
梯度下降算法
吸取的经验教训
文章中举的大部分例子我都看不懂,可以先选择新跳过的,在这方面耽误了很多时间。