The Art, Science, and Engineering of Fuzzing: A Survey 翻译

翻译

The Art, Science, and Engineering of Fuzzing: A Survey

综述:模糊测试的艺术、科学与工程

👉 原文地址

摘要

在当今可用的许多软件漏洞发现技术中,模糊测试由于其概念简单性,较低的部署障碍以及在发现现实世界软件漏洞中的大量经验证据而一直非常受欢迎。 从较高的意义上讲,模糊是指重复运行程序的过程,生成的输入可能在语法或语义上格式错误。 近年来,尽管研究人员和从业人员都付出了巨大的努力来改善模糊测试,但工作量的激增也使人们很难获得模糊测试的全面一致的观点。 为了帮助维护和增加众多模糊测试文献的连贯性,本文提出了一个统一的通用模糊测试模型以及当前模糊测试文献的分类法。 我们通过调查使现代模糊器有效的相关文献在艺术,科学和工程方面的创新,有条不紊地探索模型模糊器每个阶段的设计决策。

1 介绍

自从1990年代初引入[152]以来,模糊测试一直是发现软件安全漏洞的最广泛采用的技术之一。 从较高的意义上讲,模糊是指重复运行程序的过程,生成的输入可能在语法或语义上格式错误。 在实践中,攻击者在诸如漏洞利用程序生成和渗透测试之类的场景中例行部署模糊测试[21],[109]; 2016年DARPA网络大挑战赛(CGC)的几支团队也在其网络推理系统中使用了模糊测试[37],[200],[9],[93]。 在这些活动的推动下,防御者已开始使用模糊测试,以试图在攻击者之前发现漏洞。 例如,著名的供应商,例如Adobe [1],Cisco [2],Google [61],[5],[15]和Microsoft [38],[8],都将模糊测试作为其安全开发实践的一部分。 最近,安全审核员[237]和开放源代码开发人员[4]也已开始使用模糊测试来评估商品软件包的安全性,并为最终用户提供某种合适的保证形式。

模糊的社区非常活跃。 在撰写本文时,仅GitHub就托管了上千个与模糊测试有关的公共存储库[86]。 正如我们将要证明的那样,文献中也包含大量的模糊测试(请参阅第5页的图1),并且越来越多的模糊测试研究出现在主要的安全会议上(例如[225],[52],[37], [176],[83],[239])。 此外,博客圈充斥着许多模糊测试的成功故事,其中有些还包含我们认为是可以在文学中永久占有一席之地的宝石。

不幸的是,研究人员和从业人员在模糊测试方面的工作激增也预示着进展受到阻碍的警告信号。 例如,某些模糊器的描述并没有超出其源代码和手册页(说的实在,行动跟上,但是没有写进一步前进的方向)。 因此,随着时间的推移,很容易失去对设计决策的跟踪以及对这些模糊器的潜在重要调整。 此外,在各种模糊测试器所使用的术语中还存在可观察到的碎片。 例如,尽管AFL [231]使用术语“测试用例最小化”来指代减少崩溃输入的大小的技术,但同一技术在funfuzz [187]中称为“测试用例减少”。 同时,尽管BFF [49]包含了一种听起来类似的技术,称为“崩溃最小化”,但该技术实际上是在设法使崩溃的输入和原始种子文件之间的位数最少不同,并且与减少输入无关 尺寸。 这使得使用发布的评估结果比较(甚至不是很难)模糊测试变得困难。 我们认为,这样的碎片化使得难以发现和传播模糊测试知识,从长远来看,这可能严重阻碍模糊测试的进展。

由于上述原因,我们认为现在是巩固和提炼模糊测试方面大量进展的最佳时机,其中许多是在three trade books (2007-2008年出版)之后发生的[79],[203],[ 205]。

在尝试统一field时,我们将从使用**§2开始介绍我们的模糊测试术语和统一的模糊测试模型**。 忠实于本文的目的,选择我们的术语以紧密反映当前的主要用法,并且我们的模型模糊器(算法1、第3页)旨在适应按分类法分类的大量模糊任务 当前的模糊文献(图1,第5页)。 通过这种设置,我们将在§3–§7中探索模型模糊器的每个阶段,并在表1(第6页)中详细介绍主要模糊器。 在每个阶段,我们都将调查相关文献,以解释设计选择,讨论重要的取舍,并重点介绍许多出色的工程工作,这些工作可帮助使现代模糊测试人员有效地完成任务

2 系统化,分类法和测试程序

“模糊”一词最初是由Miller等人创造的。 在1990年,它指的是“生成目标程序要使用的随机字符流”的程序[152,p. 4]。 从那时起,模糊的概念及其作用(“模糊”)就出现在各种各样的环境中,包括动态符号执行[90],[226],基于语法的测试用例生成[88],[105], [213],权限测试[24],[80],行为测试[122],[175],[224],复杂性测试[135],[222],内核测试[216],[196],[186 ],表示依赖测试[121],功能检测[227],鲁棒性评估[223],漏洞利用开发[111],GUI测试[197],签名生成[72]和渗透测试[81],[156]。 为了系统化来自大量模糊测试文献的知识,让我们首先介绍从现代用途中提取的模糊测试术语。

2.1 Fuzzing & Fuzz Testing

直观上,fuzzing是使用“fuzz inputs”运行被测程序(Program Under Test,PUT)的操作。 尊重Miller等人,我们认为模糊输入是PUT可能不需要的输入,即PUT可能会错误处理并触发PUT开发人员意想不到的行为的输入。 为了抓住这个iead,我们将术语fuzzing定义如下。

Definition 1 (Fuzzing). Fuzzing is the execution of the PUT using input(s) sampled from an input space (the “fuzz input space”) that protrudes the expected input space of the PUT.

以下是三个备注。 首先,尽管通常会看到模糊输入空间包含预期的输入空间,但这不是必需的。其次,实际上,模糊测试几乎肯定会运行许多次迭代。 因此,在上面编写“repeated executions”仍然会非常准确。第三,采样过程不一定是随机的,正如我们将在§5中看到的那样。

Fuzz testing 是使用fuzzing的一种软件测试技术。 为了区别于其他程序并兑现我们认为是其最突出的目的,我们认为它的特定目标是查找与安全相关的错误,其中包括程序崩溃。 此外,我们还定义了fuzzer和fuzz campaign,这两个都是fuzz testing中的常用术语:

Definition 2 (Fuzz Testing). Fuzz testing is the use of fuzzing to test if a PUT violates a security policy.

Definition 3 (Fuzzer). A fuzzer is a program that performs fuzz testing on a PUT.

Definition 4 (Fuzz Campaign). A fuzz campaign is a specific execution of a fuzzer on a PUT with a specific security policy.

通过fuzz campaign运行PUT的目标是发现违反指定安全策略的错误[26]。例如,早期的模糊测试人员采用的安全策略仅测试生成的输入(测试用例)是否使PUT崩溃。 但是,fuzz testing实际上可以用来测试执行过程中可观察到的任何安全策略,例如EM-enforceable [183]。 判断执行是否违反安全策略的特定机制称为bug oracle。

Definition 5 (Bug Oracle). A bug oracle is a program, perhaps as part of a fuzzer, that determines whether a given execution of the PUT violates a specific security policy.

我们将fuzzer实现的算法简称为“fuzz algorithm”。 几乎所有的fuzz algorithm都依赖于PUT以外的某些参数。参数的每个具体设置都是模糊配置:

Definition 6 (Fuzz Configuration). A fuzz configuration of a fuzz algorithm comprises the parameter value(s) that control(s) the fuzz algorithm.

模糊配置的定义旨在广泛。 请注意,模糊配置中的值类型取决于模糊算法的类型。 例如,将随机字节流发送到PUT [152]的模糊算法具有简单的配置空间{(PUT)}。 另一方面,复杂的模糊测试器包含的算法可以接受一组配置,并且随着时间的推移会不断发展(包括添加和删除配置)。 例如,CERT BFF [49]在运动过程中会同时改变突变率和种子,因此其配置空间为{(PUT,s1,r1),(PUT,s2,r2),…。 。 }。 种子是PUT的(通常结构良好)输入,用于通过修改种子来生成测试用例。 Fuzzer通常维护种子的集合,并且某些Fuzzer会随着Fuzz活动的进行而扩展该集合。 该集合称为种子池。 最后,模糊器能够在每个配置中存储一些数据。 例如,覆盖率指导的模糊器可以在每个配置中存储已达到的覆盖率。

2.2 论文选择标准

为了达到明确的范围,我们选择在2008年1月至2019年2月的4个主要安全会议和3个主要软件工程会议的最后会议记录中纳入有关模糊测试的所有出版物。按字母顺序,前者包括(i) ACM Conference on Computer and Communications Security (CCS), (ii) IEEE Symposium on Security and Privacy (S&P), (iii) Network and Distributed System Security Symposium (NDSS), and (iv) USENIX Security Symposium (USEC); 后者包括 (i) ACM International Symposium on the Foundations of Software Engineering (FSE), (ii) IEEE/ACM International Conference on Automated Software Engineering (ASE), and (iii) International Conference on Software Engineering (ICSE). 对于出现在其他场所或媒体中的文字,我们根据自己对它们的相关性的判断将其包括在内。

如第2.1节所述,模糊测试仅将自身与软件测试区分开来,因为模糊测试与安全相关。 从理论上讲,专注于安全性错误并不意味着测试过程会与选择错误预言家有所不同。 但是,实践中使用的技术通常会有所不同。 设计测试工具时,通常会假定您可以访问源代码以及有关PUT的一些知识。这样的假设通常驱使测试工具的开发与模糊测试工具相比具有不同的特征,而模糊测试工具则更可能被PUT开发人员以外的各方采用。 尽管如此,这两个领域仍然彼此密切相关。 因此,当我们不确定是否将和“模糊测试”相关的出版物包括在本调查中时,我们遵循一条简单的经验法则:如果在出版物中出现模糊一词,则将其包括在内。

2.3 Fuzz Testing Algorithm

我们提出了一种用于模糊测试的通用算法,即算法1,我们认为它已在模型模糊器中实现。 它足够通用以适应现有的模糊测试技术,包括第2.4节中定义的黑,灰和白盒模糊测试。 算法1将一组模糊配置C和一个超时tlimit作为输入,并输出一组已发现的错误B。它由两部分组成。 第一部分是PREPROCESS功能,该功能在 fuzz campaign的开始时执行。 第二部分是循环内的五个功能系列:SCHEDULE,INPUTGEN,INPUTEVAL,CONFUPDATE和CONTINUE。此循环的每次执行都称为模糊迭代,每次INPUTEVAL在测试用例上执行PUT,称为fuzz run。 请注意,某些模糊器无法实现全部五个功能。 例如,要为Radamsa [102]建模(该模型从不更fuzz配置集),始终将当前配置集保持不变。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CDte2Fha-1614585704718)(./翻译.assets/算法1_fuzz_testing.png)]

  1. PREPROCESS © → C

    用户向PREPROCESS提供一组模糊配置作为输入,并且它返回一组可能经过修改的模糊配置。 根据模糊算法,PREPROCESS 可能会执行各种操作,例如将检测代码插入PUT或测量种子文件的执行速度。 参见§3(预处理)

  2.  SCHEDULE  ( C , t elapsed  , t limit  ) → conf ⁡ \text { SCHEDULE }\left(\mathbb{C}, t_{\text {elapsed }}, t_{\text {limit }}\right) \rightarrow \operatorname{conf}  SCHEDULE (C,telapsed ,tlimit )conf

    SCHEDULE使用当前的fuzz configurations,当前使用的时间,超时时间作为输入,从而选择使用一个fuzz configuration 进行模糊测试迭代。参见§4(调度)

  3. INPUTGEN (conf) → tcs

    输入INPUTGEN将模糊配置作为输入,并返回一组具体的测试用例tcs作为输出。生成测试用例时,INPUTGEN 使用conf中的特定参数。 有些模糊器使用conf中的种子来生成测试用例,而另一些模糊器则使用模型或语法作为参数。 参见§5(生成测试用例)

  4.  INPUTEVAL (conf, tcs,  O bug  ) → B ′  , execinfos  \text { INPUTEVAL (conf, tcs, } \left.O_{\text {bug }}\right) \rightarrow \mathbb{B}^{\prime} \text { , execinfos }  INPUTEVAL (conf, tcs, Obug )B , execinfos 

    INPUTEVAL以模糊配置conf,一组测试用例tcs和一个bug oracle O bug  O_{\text {bug }} Obug 作为输入。 它在tcs上执行PUT,并使用bug oracle O bug  O_{\text {bug }} Obug 检查执行是否违反了安全策略。 然后,它输出找到的错误集B’和有关每个fuzz runs execinfos的信息,这些信息可用于更新模糊配置。 我们假设Obug嵌入在我们的模型模糊器中。 参见§6。

  5. CONFUPDATE(C, conf, execinfos) → C

    CONFUPDATE将一组模糊测试配置C,当前配置conf和有关每个模糊测试的信息运行execinfos作为输入。 它可以更新fuzz配置C的集合。例如,许多灰盒fuzzer基于execinfos减少了C中fuzz configurations 的数量。 参见§7。

  6. CONTINUE © → {True, False}

    CONTINUE将一组模糊配置C作为输入,并输出一个布尔值,该布尔值指示是否应该进行新的模糊迭代。 此功能对于为白盒模糊测试模型建模很有用,当没有更多可发现的路径时,该模糊测试可以终止。

2.4 模糊测试器的分类

在本文中,我们根据模糊器在每次模糊运行中观察到的语义的粒度将模糊器分为三类。 这三组分别称为黑盒,灰盒和白盒模糊器,我们在下面对其进行定义。 注意,这种分类不同于传统的软件测试,传统的软件测试只有两个主要类别(黑盒和白盒测试)[158]。 正如我们将在第2.4.3节中讨论的那样,灰盒模糊测试是白盒模糊测试的一种变体,只能从每次模糊测试运行中获取部分信息。

2.4.1 黑盒测试

“black-box”一词通常用于软件测试[158],[32]和模糊测试中,它们表示看不到PUT内部的技术,这些技术只能观察PUT的输入/输出行为, 它是一个黑匣子。 在软件测试中,黑盒测试也称为IO驱动或数据驱动测试[158]。 大多数传统的模糊器[13],[103],[49],[6],[50]都属于此类。 一些现代的模糊测试工具,例如funfuzz [187]和Peach [76],也将有关输入的结构信息考虑在内,以生成更有意义的测试用例,同时保持不检查PUT的特性。 在自适应随机测试中也使用了类似的直觉[57]。

2.4.2 白盒测试

另一方面,白盒模糊测试[90]通过分析PUT 的内部以及执行PUT时收集的信息来生成测试用例。因此,白盒模糊测试仪能够系统地探索PUT的状态空间。 白盒模糊测试一词是Godefroid [87]在2007年提出的,指动态符号执行(DSE),它是符号执行的一种变体[39],[126],[108]。 在DSE中,符号执行和具体执行同时进行,其中具体程序状态用于简化符号约束,例如,具体化系统调用。 因此,DSE通常被称为conconolic测试(具体+符号)[191],[89]。 另外,白盒模糊测试也已经被用来描述采用污点分析的模糊测试[84]。 白盒模糊测试的开销通常比黑盒模糊测试的开销高得多。 部分原因是DSE实施[90],[46],[25]经常采用动态工具和SMT解决方案[155]。虽然DSE是一个活跃的研究领域[90],[88],[38],[172],[112],但许多DSE并不是白盒测试工具,因为它们的目的不是发现安全漏洞。 因此,本文没有提供有关DSE的全面调查,我们为读者提供了有关非安全应用程序DSE的更多信息的近期调查论文[17],[185]。

2.4.3 灰盒测试

一些模糊器[78],[68],[205]采取中间地方法,称为灰盒模糊测试。 通常,灰盒模糊器可以获取PUT和/或其执行内部的一些信息。 与白盒模糊测试器不同的是,灰盒模糊测试器并不考虑PUT的全部语义; 相反,他们可以在PUT上执行轻量级静态分析和/或收集有关其执行的动态信息,例如代码覆盖率。 灰盒模糊测试器依赖于近似的不完美信息,以提高速度并能够测试更多输入。 尽管安全专家之间通常会达成共识,但黑盒,灰盒和白盒模糊测试之间的区别并不总是很清楚。黑盒子的模糊器可能会收集一些有关模糊运行的信息,而白盒子的模糊器通常会使用一些近似值。在本次调查中,特别是在表1中对模糊测试进行分类时,我们使用了我们自己的(最佳)判断。

灰盒模糊器的早期示例是EFS [68],它使用从每次模糊运行收集的代码覆盖率来通过进化算法生成测试用例。 Randoop [166]也使用了类似的方法,尽管它没有针对安全漏洞。 诸如AFL [231]和VUzzer [176]之类的现代模糊器就是此类产品的典范。

2.5 Fuzzer族谱和概述

图1(第5页)按时间顺序展示了我们对现有模糊器的分类。 从米勒等人的开创性工作开始。 [152],我们手动选择了流行的模糊器,这些模糊器要么出现在大型会议上,要么获得了超过100个GitHub星星,并以图表的形式显示了它们的关系。黑盒模糊器在图的左半部分,灰色和白盒模糊器在图的右半部分。 此外,根据PUT使用的输入类型将模糊器细分:文件,网络,UI,Web,内核I / O或线程(对于并发模糊器)

表1(第6页)详细介绍了图1中最著名的模糊器所使用的技术。由于空间限制,我们不得不省略图1中的某些模糊器。 每个模糊器都是基于其对模型模糊器的五个功能的实现进行总结的,而其他部分则提供了有关该模糊器的其他详细信息。 我们在下面的每一列中描述了属性。

(这两部分的图片比较大,不搬运过来了)

3 预处理

一些Fuzzer在第一次Fuzz迭代之前修改了初始的Fuzz配置集。 这种预处理通常用于检测PUT,清除潜在的冗余配置(即“种子选择” [177]),修剪种子并生成驱动程序。 如第5.1.1节(第9页)所述,PR E P R O C E S S也可用于为将来的输入生成(IN P U TGE N)准备模型。

3.1 检测(instrumentation,插桩,注入)

收集信息的方式:processor traces 、system call usage、instrument.

根据××,插桩可以分为两类:静态插桩和动态插桩。

静态插桩:除了源代码插桩,研究者也开发出二进制层次的插桩。

动态插桩:知名的动态插桩工具(dynamic instrumentation ):DynInst [173], DynamoRIO [42], Pin [144], Valgrind [163],and QEMU [33].

3.1.1 执行反馈

通过反馈来进化测试用例。

AFL使用bit vector来存储边覆盖率,这会导致路径碰撞。(可能的意思是,两条执行路径有交集)

CollAFL通过路径敏感哈希函数,来解决路径碰撞问题。

LibFuzzer和Syzkaller使用节点覆盖率,反馈

Honggfuzz允许使用者选择执行的反馈方式。

3.1.2 在内存中模糊测试

程序比较大,启动比较慢,可以在内存中创建其快照。

一些模糊测试器,将被测试程序像函数一样,不停的测试,而不是重新初始化。我们称这种技术为in-memory API fuzzing.(eg,AFL中的persistent模式)。这样做,可能有潜在的问题,而且问题可能无法重现。(感觉有点类似于,可重载函数这个概念)

3.1.3 线程调度

现有的工作证明,通过插桩,随机显示的调用线程,可以有效的触发竞争条件。

3.2 种子选择

很多种子可能都合法,问题是如果两个种子的执行路径都相同,我们只需要留其一在种子库中就好,这里涉及到种子选择问题。【种子数量上减少】

有几种方法和工具来处理种子选择问题。最通用的方法是找到种子最小集合,这个集合有最大的代码覆盖率。Miller’s report中展示增加1%的代码覆盖率,可以增加.92%发现种子。

模糊测试使用各种不同的覆盖率指标。 AFL的最小集基于分支覆盖率,每个分支上都有一个对数计数器。 该决定的基本原理是仅在分支数量的数量级不同时才允许它们被认为是不同的。 Honggfuzz [204]根据已执行的指令,已执行的分支和唯一的基本块的数量来计算覆盖率。 此度量标准允许模糊器将更长的执行添加到最小集,这有助于发现拒绝服务漏洞或性能问题。

3.3 种子修剪

减小种子的大小,减少内存开销,提升吞吐率。

3.4 准备驱动程序

对库和内核不方便直接测试,准备驱动程序。

4 调度

调度意味着为下一个模糊迭代选择一个模糊配置。

对于BFF和AFLFast,其成功的主要原因在于创新的调度算法。

4.1 模糊配置调度(FCS)问题

希望选择的配置可以找到独特的bug或者更大的代码覆盖率。

4.2 黑盒的FCS算法

对于黑盒测试,输出结果是FCS能够使用的唯一信息。输出结果包含:crashes,bugs,spend of time。Householder和Foote [107]最早研究了如何在CERT BFF黑盒突变模糊测试器中利用这些信息[49](选择哪些(#bug /#runs)的用例变异)。Woo等人对此做了多方面的改进。(我没看懂这里的描述思路)。

4.3 灰盒的FCS算法

可以有很多配置。每个配置可以有一个“适度值”。一个进化算法,选择合适的配置,并应用的遗传转化中。这里分为三个步骤:如何设置配置适度值,根据哪种策略选择配置,选择该配置之后如何应用。

AFLFast对AFL上面三个方面的每一个方面都进行了改进。

精读:AFLFast_Coverage-based greybox fuzzing as markov chain – panda

AFLGo [36]通过修改AFLFast的优先级属性来扩展AFLFast,以针对特定的程序位置。
Hawkeye [53]通过在种子调度和输入生成中利用静态分析来进一步改善定向模糊。 FairFuzz [136]通过为每对种子和稀有分支使用突变掩码来指导运动来行使稀有分支。 QTEP [218]使用静态分析来推断二进制文件的哪个部分更“有故障”,并对覆盖它们的配置进行优先级排序

??

5 输入生成

分为两种:基于模型生成的模糊测试器,基于突变的模糊测试器。

5.1 基于模型的模糊测试器

基于模型的模糊器基于描述给定PUT可以接受的输入或执行的给定模型来生成测试用例,例如精确表征输入格式的语法或不太精确的约束(例如标识文件类型的魔术值)。

5.1.1 预定义模型

有两种。

第一种是可以由用户配置的模型。接受用户提供的规范、允许穿件自己的输入模型的API、接受EBNF。

另一种是,模型已经被嵌入在模糊测试器中了。生成DOM的DOMfuzz,生成JavaScript的jsfunfuzz等。

5.1.2 推断模型

最近,推论模型而不是依赖于预定义的或用户提供的模型已经越来越受人们的青睐。
尽管有大量关于自动输入格式和协议逆向工程的已发表研究[66],[45],[141],[63],[28],但只有少数模糊测试者利用了这些技术。 与工具(第3.1节)相似,模型推断可以在PR E P R O C E S S S或CO N FUP D A T E中进行。(给定一组种子和一个语法,Skyfire [217]使用一种数据驱动的方法来推断概率性的上下文相关语法,然后使用它来生成一组新的种子。)

5.1.3 编码模型

文件有一定的格式。打开特定格式的文件,需要对应的软件。如果我们想测试处理mp4,.xls等文件格式的程序,我们需要将文件格式作为一种隐式模型。

5.2 无模型(基于突变)的模糊器

通过仅更改有效文件的一小部分,通常可以生成一个新的测试用例,该用例大部分是有效的,但也包含异常值以触发PUT崩溃。下面是各种突变种子的方法。

5.2.1 位翻转

一些模糊器仅翻转固定数量的位数,而其他一些则确定随机翻转的位数。(用户可以控制突变率)SymFuzz [52]表明,模糊测试性能对突变率很敏感,而且没有一个单一的比率对所有PUT都适用。 有几种方法可以找到良好的突变率。 BFF [49]和FOE [50]为每个种子使用按比例缩放的突变比率集,并为证明具有统计学上的有效性的突变比率分配更多的迭代次数[107]。 SymFuzz [52]利用白盒程序分析来推断每个种子的良好突变率

5.2.2 算术变异

AFL [231]和honggfuzz [204]包含另一种变异操作,它们将选定的字节序列视为整数,并对该值执行简单的算术运算。(给加减上一个很小的值)

5.2.3 基于块的突变

块是字节序。可以随机插入,删除,替换,排序。

5.2.4 基于字典的变异

例如,当对整数进行突变时,AFL [231],honggfuzz [204]和LibFuzzer [7]使用诸如0,-1和1之类的值。 Radamsa [102]使用Unicode字符串,而GPF [6]使用格式化字符(例如%x和%s)来使字符串变异[55]。(这些0,,1,1是字典。不知道这些字典有没有暴露出来,提供给用户修改)

5.3 白盒模糊测试

并不是所有的白盒模糊测试器,都是动态符号执行器。

5.3.1 动态符号执行

动态符号执行,代价比较高。可以选择特定的代码片段使用动态符号执行,其他使用灰盒测试。即,动态符号执行和灰盒测试可以交替执行。(这里怎么处理的?如果动态符号执行在中间,符号求解出来的输入,也无法通过前面的代码得到合适的输入。)Driller和Cyberdyne已经在DARPA Cyber Grand Challenge中使用了这个技术,并有效。

QSYM [230]试图通过实现快速的conolicly执行引擎来改善灰盒和白盒模糊测试之间的集成。
DigFuzz [239]通过首先估算使用灰盒模糊测试行使每条路径的概率然后使其白盒模糊测试器集中于那些被认为最具挑战性的路径,从而优化了白盒模糊测试之间的切换。 灰箱模糊测试。

5.3.2 引导性模糊测试

第一步,进行昂贵的程序分析以获取有关PUT的有用信息。第二步,在先前分析的指导下生成测试用例。

TaintScope通过细粒度的污点分析,找到输入中经常出现的字节。

VUzzer [176]和GRT [145]利用静态和动态分析技术从PUT中提取控制和数据流特征,并使用它们来指导输入生成

RedQueen

在这篇文章中,作者提出了一种非常简单的提升fuzz效率的方法,基于一个简单的假设,即一个程序的输入很多时候被直接用来进行逻辑判断,所以在tracing中可以找到对应数据。虽然可能不能面对所有情况,但还是比较通用的,而且性能很好。

5.3.3 被测试程序变异

模糊测试有两个挑战:Magic num,checksum。TainScope(修改被测试程序)绕过checksum。如果程序出现crash,使用输入测试没有被修改的程序。。

当不能访问到新的路径时,T-fuzz会去掉check,以保证fuzz能继续进行,发现新的路径和bug。这个方法有2个问题:1.去除check,导致结果不准确并会产生误报;2. 即使是真的bug,那么这个crash的input也有可能在原始的程序中执行不会引发bug。作为辅助的后处理步骤,一个符号执行器将过滤这些误报、复现真的bug。

6 输入评估

6.1 Bug Oracles

程序可能执行出错(非人为设定意愿的方式执行),但是并没有crash。为了减轻这种情况,研究人员提出了各种有效的程序转换,以检测不安全或有害的程序行为并中止程序。 这些通常被称为sanitizers。

6.1.1 内存和类型安全

内存安全错误可以分为两类:空间错误和时间错误。

Address Sanitizer(ASan)是一个快速的内存错误检测工具。MEDS [101] improves on ASan

6.1.2 未定义的行为

诸如C之类的语言包含许多语言规范未定义的行为。 编译器可以通过多种方式自由处理这些构造。[Memory Sanitizer、UBSan、TSan]

6.1.3 输入验证

测试输入验证漏洞(例如XSS(跨站点脚本)和SQL注入漏洞)是一个具有挑战性的问题,因为它需要了解为Web浏览器和数据库引擎提供动力的非常复杂的解析器的行为。[KameleonFuzz 、 µ4SQLi]

6.1.4 语义差异

语义上的bug,通常使用differential testing[148]. 使用差异测试,测试相似的程序。

6.2 执行优化

内存执行、fork server等。

6.3 分流

分流是分析和报告导致违反策略的测试用例的过程。 分类可以分为三个步骤:重复数据删除,优先级划分和测试用例最小化。

6.3.1 重复数据删除

触发相同的错误,删除对应的测试用例,保留一个。

当前,实践中使用了三种主要的重复数据删除实现:堆栈回溯哈希,基于coverage的重复数据删除和语义感知的重复数据删除

6.3.2 优先级和可利用性

通过优先级划分,确定崩溃的可利用性。

6.3.3 测试用例最小化

有选择地生成比原始示例更小和更简单但仍会引起违规的测试用例的过程

7 配置更新

7.1 种子库更新

LibFuzzer [7],Honggfuzz [204],go-fuzz [215]和Steelix [138]会检测所有比较,并将任何在比较中取得进展的测试用例添加到种子库中。

7.2 维护一个最小集

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值