2017 S&P-Skyfire: Data-Driven Seed Generation for Fuzzing

摘要:以高度结构化的文件作为输入的抽象程序通常分阶段处理输入:语法解析、语义检查和应用程序执行。深层bug通常隐藏在应用程序执行阶段,自动生成测试输入以触发它们并非易事。基于变异的模糊化通过随机或启发式修改格式良好的种子输入来生成测试输入。大多数输入在早期语法分析阶段被拒绝。不同的是,基于生成的模糊化从规范(例如语法)生成输入。它们可以快速地将模糊化带到语法分析阶段之外。然而,大多数输入无法通过语义检查(例如,违反语义规则),这限制了它们发现深层错误的能力。
在本文中,我们提出了一种新的数据驱动种子生成方法Skyfire,它利用大量现有样本中的知识,为处理高度结构化输入的模糊程序生成分布良好的种子输入。Skyfire以语料库和语法作为输入,包括两个步骤。Skyfire的第一步学习概率上下文敏感语法(PCSG),以指定语法特征和语义规则,然后第二步利用学习到的PCSG生成种子输入。
我们将收集的样本和Skyfire生成的输入作为AFL的种子,用于模糊几个开源XSLT和XML引擎(即Sablotron、libxslt和libxml2)。结果表明,Skyfire可以生成分布良好的输入,从而显著提高代码覆盖率(即平均20%的行覆盖率和15%的功能覆盖率)和模糊器的错误发现能力。我们还使用Skyfire生成的输入来模糊Internet Explorer 11的封闭源代码JavaScript和渲染引擎。我们总共发现了19个新的内存损坏漏洞(其中有16个新漏洞)和32个拒绝服务漏洞。

一、引言

在本文中,我们提出了一种新的数据驱动种子生成方法,名为Skyfire1。它利用大量样本(即语料库)自动提取语法和语义规则的知识,并利用这些知识为处理高度结构化输入的模糊程序生成分布良好的种子输入。从这个意义上说,Skyfire与基于变异的模糊化方法是正交的,为它们提供高质量的种子输入,并提高它们在处理高度结构化输入的程序中的效率和有效性。此外,Skyfire改进了现有的基于生成的模糊化方法,即在语义检查阶段之外进行模糊化探索,以达到应用程序执行阶段,从而在不需要任何手动规范任务的情况下查找深层缺陷。
基本上,Skyfire将语料库和语法作为输入,并分两步生成种子输入,如图2所示。第一步根据语法将收集的样本(即语料库)解析为抽象语法树(AST),并学习概率上下文敏感语法(PCSG),该语法同时指定语法特征和语义规则。与基于生成的模糊化中广泛使用的上下文无关语法不同,PCSG中的每个产生式规则都与可以应用产生式规则的上下文以及在该上下文下应用产生式规则的概率相关联。
在第二步中,Skyfire首先通过在非终端符号上迭代选择并应用满足上下文的产生式规则生成种子输入,直到没有非终端符号结果字符串中的符号。在这个过程中,我们更喜欢低概率产生式规则,而不是高概率产生式规则,以产生具有不同语法结构的不常见输入。Skyfire然后进行种子选择,过滤出具有相同代码覆盖率的种子,以减少冗余。最后,Skyfire根据产生式规则将AST中的叶级节点随机替换为相同类型的节点,从而变异剩余的种子输入,这在保持语法结构的同时以不同的方式引入语义变化。
为了评估我们的方法的有效性和通用性,我们收集了XSL、XML和JavaScript的样本。然后,我们将收集的样本和Skyfire生成的输入作为种子输入AFL[7],以模糊几个开源XSLT和XML引擎(即Sablotron、libxslt和libxml2)。我们还使用Skyfire生成的输入来模糊Internet Explorer 11中的closedsource JavaScript和渲染引擎。评估结果表明,i)Skyfire可以生成分布良好的输入,从而有效地提高模糊器的代码覆盖率(即,平均线覆盖率为20%,功能覆盖率为15%);ii)Skyfire可以显著提高模糊者发现漏洞的能力。我们发现了19个新的内存损坏漏洞(其中我们发现了16个新漏洞),以及32个新的拒绝服务漏洞(包括堆栈耗尽、空指针解引用和断言失败)。
这项工作的主要贡献如下:我们建议从现有样本中学习概率上下文敏感语法(PCSG),以描述高度结构化输入的语法特征和语义规则我们建议利用PCSG生成具有不同语法结构的种子输入,应用种子选择以减少种子冗余,并执行种子变异以引入不同的语义变化,其目的是为处理高度结构化输入的模糊程序生成正确、多样和不常见的种子我们通过使用生成的输入对几个XSLT、XML和JavaScript/呈现引擎进行模糊化来评估Skyfire,极大地提高了代码覆盖率,并发现了16个新漏洞。本文的其余部分结构如下。
在这里插入图片描述
Skyfire将语料库和语法作为输入,并分两步生成种子输入,如图2所示。第一步根据语法将收集的样本(即语料库)解析为抽象语法树(AST),并学习概率上下文敏感语法(PCSG),该语法同时指定语法特征和语义规则。与基于生成的模糊化中广泛使用的上下文无关语法不同,PCSG中的每个产生式规则都与可以应用产生式规则的上下文以及在该上下文下应用产生式规则的概率相关联。
在第二步中,Skyfirefirst通过在非终端符号上迭代选择并应用满足上下文的产生式规则来生成种子输入,直到电影变形金刚中没有非终端1汽车人科学家。结果字符串中的符号。在这个过程中,我们更喜欢低概率产生式规则,而不是高概率产生式规则,以产生具有不同语法结构的不常见输入。Skyfire然后进行种子选择,过滤出具有相同代码覆盖率的种子,以减少冗余。最后,Skyfire根据产生式规则将AST中的叶级节点随机替换为相同类型的节点,从而变异剩余的种子输入,这在保持语法结构的同时以不同的方式引入语义变化。

二、方法概述

A. 目标计划

B. 天火概述

为了确保对处理高度结构化输入的程序进行模糊测试的广度和深度,我们的种子生成方法有三个主要目标。第一个目标是生成 正确的 种子,这保证生成的大多数输入在语法和语义上都是有效的。此类输入可以防止模糊测试在语法解析和语义检查阶段卡住,并有助于快速进入应用程序执行阶段。
第二个目标是生成 不同的 种子,这确保了语法和语义规则方面输入的多样性。这种多样性可以帮助快速覆盖不同的功能模块,而传统的基于突变的模糊方法通常很难达到这些功能模块。
第三个目标是生成 不常见的 种子,这可确保输入不常见到足以到达模糊程度较低的程序代码并触发意外的程序行为。与普通输入相比,此类输入通常具有更高的揭示新错误的可能性 ,并且 be 可以作为模糊测试器变异和探索未探索程序行为的良好种子。
遵循这三个主要目标,我们提出了一种数据驱动的种子生成方法,称为Skyfire。图 2 概述了我们的方法,该方法采用语料库和语法作为输入,并通过两个步骤生成种子输入:学习和生成。Skyfire的输出可以作为种子馈送到模糊测试器(例如,AFL [7])以开始模糊测试。语料库包含从 Internet 爬取的大量样本。语法是指示例的上下文无关语法,通常是公开的(例如,可以在ANTLR社区中找到不同语言的语法[26])。

三、 PCSG学习

A. 概率上下文相关语法

我们没有捕获所有类型的语义规则,而是以这样一种方式定义上下文:大多数语义规则都可以被表达,它们可以在学习步骤中被有效地学习,并在生成步骤中被有效地检查。请注意,表I中的前五条语义规则是可以捕获的,但由于建模上下文需要大量信息,最后两条无法表达。目前,我们认为这样的层次关系足以捕获语义规则的多样性,同时保持低冗余。然而,可以扩展上下文(例如,通过使用多个兄弟姐妹和/或通过使用更多或更少的祖先)以纳入此类语义规则。另一方面,我们需要生成足够罕见的输入,以触发异常的程序行为。因此,我们定义了一种概率上下文敏感语法(PCSG)来捕获语料库中产生式规则的频率。
在这里插入图片描述
这里R+表示非负实数的集合。定义3确保对于给定的非终端符号,适用于所有上下文的产生式规则的概率总和为1。总之,通过集成产生式规则的上下文和概率,PCSG比CFG或CSG更具表现力,后者在单个数据结构中总结了样本的知识。

B. 学习概率上下文相关语法

所有学习到的生产规则都保存在池中。它们将在生成步骤中用于生成分布良好的输入,如第四节所述。请注意,为了提高效率,这里采用简单的学习方法,我们将研究应用高级学习算法(例如,深度学习[27])的可能性。

四、 种子世代

A. 种子生成

给定学习到的PCSG,我们可以通过最左边的派生生成一组种子输入(见定义4)。具体来说,为了生成输入t,我们可以首先将t设置为PCSG的开始符号,并迭代地应用以下步骤,直到t中没有非终端符号:i)获取t中最左侧的非终端符号l和相应的上下文c,ii)从Rl中随机选择一个产生式规则r,其左侧为l给定c,以及iii)将r应用于t中的l,基于最左边的随机派生,在达到时间预算或生成预定义数量的种子输入时终止。由于PCSG的性质,生成的大多数输入在语法和语义规则方面都是正确的。请注意,如果在达到时间预算时t仍然包含非端子,则t将被丢弃。
问题。首先,由于产生式规则可以是递归的,因此生成过程可能是非终止的。因此,通过应用递归产生式规则来扩展非终端符号可能会导致字符串再次包含相同的非终端符号。例如,XSL中的一个元素可以包含一个内容,而该内容可以包含另一个元素。此外,当一个产生式规则可以包含许多非终结符符号时,这个问题变得更加严重。例如,一个内容可以包含数百个元素。
其次,生成的输入可能会变得不必要的复杂,因为产生式规则是递归的(即,在深度上增加复杂性),或者具有许多非终端符号(即,在广度上增加复杂性)。因此,生成的输入可能非常大,可能会被模糊器直接拒绝(例如,AFL[7]默认情况下拒绝接受大于1MB的输入)。
启发1:支持低概率产生式规则。我们根据经验将0.9确定为一个好的阈值。
启发式2:支持低频产生式规则,并限制同一产生式规则的应用程序数量。我们首先修剪那些已经应用了3次的规则(这是根据经验建立的),然后更喜欢低频规则而不是高频规则。
启发3:支持低复杂度的产生式规则。
启发式4:限制规则应用程序的总数。为了减少生成的输入的不必要的深度复杂性,我们根据经验将生成输入时的规则应用程序总数限制为200(第17行)。

B. 种子选择

我们使用gcov[29]获得开放源代码程序的行覆盖率和函数覆盖率,并使用基于PIN[30]的静态分析和覆盖工具获得封闭源代码程序的基本块覆盖率。如果一个输入触发了新的块覆盖,我们将其作为种子保存。

C. 种子突变

我们根据产生式规则将AST中的一个叶级节点随机替换为相同类型的节点,从而对每个输入进行轻微的变异,从而对叶节点的分布产生特殊的干扰。换句话说,只有右边只包含终端符号的产生式规则才会在这个变异过程中使用。与fuzzers中的小步突变(例如byteflipping)相比,我们的突变可以被视为大步突变,很难通过fuzzers的小步突变实现。通过随机翻转位,很难从version=“1.0”到encoding=“utf-8”。最后,变异后的输入可以输入模糊器。

五、实施和评价

A.评估设置

为了评估我们方法的有效性和通用性,我们选择XSL、XML以及JavaScript作为种子生成的目标语言。这些语言的语法可在ANTLR社区获得[26]。请注意,XSL和XML共享相同的语法,但有不同的语义规则。
研究问题。使用之前的实验设置,我们的目标是通过实验回答以下研究问题:•RQ1:Skyfire能否为模糊器找到bug生成良好的种子?(第V-B节)•RQ2:Skyfire能否提高目标程序的代码覆盖率?(第V-C节)•RQ3:提议的PCSG和Skyfire中使用的四种启发式算法是否有效地生成种子?(V-D部分)•RQ4:天火的效率如何?(第V-E节)

B.发现的脆弱性和漏洞(RQ1)

Skyfire可以为模糊器生成高质量的种子输入,从而使模糊器不断检测错误,并显着提高模糊器发现错误和漏洞的能力。

C. 代码覆盖率 (RQ2)

Skyfire可以为模糊测试器生成分布良好的输入,从而显著提高模糊器的代码覆盖率(例如,行覆盖率为20%,函数覆盖率为15%)。

D. 上下文和启发式的有效性 (RQ3)

Skyfire中使用的上下文和启发式方法在生成种子方面都是有效的。特别是,上下文可以帮助生成语义上有效的种子,以便它们可以到达应用程序执行阶段。启发式方法可以帮助有效地培育分布良好的种子,并降低不必要的复杂性。

E. 性能开销 (RQ4)

Skyfire在学习和生成步骤方面是可扩展的。

F. 案例研究和讨论

G. JavaScript 的初步结果

六、 相关工作

A.基于突变的模糊化

基于突变的模糊化通常通过位翻转和令牌插入等突变算子修改格式良好的种子输入来生成输入。这种修改可以是完全随机的[1],也可以由不同的启发法引导。
AFL[7]应用了一种新型的编译时工具和遗传算法来自动发现有趣的测试输入,这些输入可以在模糊程序中触发新的内部状态。AFL将从一个基本块到另一个基本块的新转换视为一种新的内部状态。在这些覆盖信息的指导下,AFL极大地提高了程序的代码覆盖率,并在安全社区得到了广泛应用。
BuzzFuzz[8]和TaintScope[9]使用污点分析来定位用于指导突变的有趣字节。具体而言,BuzzFuzz[8]应用动态污点分析自动定位原始种子输入中影响在易受攻击点(即程序可能包含错误的点)使用的值的区域。BuzzFuzz然后通过模糊原始种子输入中的这些识别区域自动生成新的测试输入。由于这些新的测试输入通常会保留原始种子输入的底层语法结构,因此它们通常可以将初始输入解析组件传递给这些语义检查组件,以便深入执行代码。类似地,TaintScope[9]首先通过分支分析技术定位基于校验和的完整性检查,并通过控制流更改技术绕过此类检查。然后,它使用污染分析以良好的形式识别这些字节并将注意力集中在修改此类字节上。
SAGE [11, 12] 和 [10] 中的方法利用符号执行来执行模糊测试。特别是,SAGE [11, 12] 实现了一种新的搜索算法,该算法可以最大化每次符号执行运行产生的新测试输入的数量。给定一个路径条件,该路径中的所有约束(而不是其中一个约束)将逐个系统地否定,与导致它的路径条件的前缀结合,然后由约束求解器求解器求解。通过这种方式,一次符号执行运行可以生成一组新的测试输入。Babic等人[10]提出了一种三级处理方法来生成可以达到程序中潜在漏洞的测试输入。它首先使用少量种子输入运行动态分析,以解决二进制代码中的间接跳转问题,并构建一个可视图下推的自动操作,以反映全局程序控制流。然后,它对推断的自动机使用静态分析来查找潜在的漏洞。最后,它使用前一阶段的结果为自动机边缘分配权重,然后使用符号执行来生成测试输入,并将其探索定向到目标潜在漏洞。
Dowser [13] 和 BORG [14] 将污点分析和符号执行相结合,以指导模糊测试。Dowser [13] 针对缓冲区溢出和下溢漏洞。它只考虑在循环中访问数组的代码,而不是程序中所有可能的指令。它使用污点分析来确定影响数组索引的输入字节。在找到所有此类候选指令集后,它会根据对它们包含有趣漏洞的可能性的估计值对它们进行排名 ,然后象征性地执行最有希望的集合以生成触发漏洞的测试输入。类似地,BORG [14] 以缓冲区过度处理错误为目标。它的工作原理是,首先使用污点分析来选择可能导致过度读取错误的缓冲区访问,然后将符号执行引导到那些实际上可能导致过度读取的程序路径上的访问。
Driller [39]以互补的方式将引信和concolic执行相结合,以发现深层错误。廉价的模糊测试用于练习应用程序的分栏,而 concolic 执行用于生成满足分隔隔间的复杂检查的输入。当模糊测试饱和且无法触发任何新的程序行为时,Driller 会切换到 concolic 执行以接触那些难以到达的分支并生成测试输入,然后切换回模糊测试。
Kargen和Shahmehri [’ 40]采取了不同的视角来执行模糊测试。他们建议在生成程序的机器代码上执行突变,而不是直接在格式良好的输入上执行突变,以便它们可以利用有关生成程序中编码的输入格式的信息来 生成高覆盖率的测试输入。
总之,这些基于突变的模糊测试方法可以有效地模糊处理非结构化或简单结构化输入(例如,图像和多媒体)的程序。但是,对于处理高度结构化输入(例如,XSL和JavaScript)的程序,它们变得无效。因此,来自基于突变的模糊测试的大多数格式错误的输入将在程序执行的早期阶段被拒绝,无法通过语法解析,这使得模糊测试者浪费了大量的时间来处理语法正确性,而只发现琐碎的解析错误,并严重限制了他们发现深层次的错误。相反,我们的方法与基于突变的模糊测试技术是正交的,因为我们专注于种子生成,因此可以将分布良好的输入种子提供给模糊测试器。

B. 基于生成的模糊测试

基于生成的模糊测试从规范生成测试输入,因此生成的输入遵循应用程序所需的格式。
Peach [15] 和 Spike [16] 使用输入模型作为规范,并结合突变来生成输入。输入模型指定数据块的格式和完整性约束,以便生成的输入可以通过完整性检查(例如,校验和)。最近,Pham等人[17]用符号执行来模拟这种基于输入模型的方法。它们使用符号执行识别程序的格式约束,并确保生成的测试的有效性,这有助于快速将探索带到解析器分支之外,并提高模糊测试的有效性。
CSmith [19]、LangFuzz [20]、IFuzzer [21]、Radamsa [41]和[18]中的方法使用上下文无关语法作为生成输入的规范。Godefroid等人[18]提出了一种动态测试生成approach,其中涉及符号执行以生成基于语法的约束,其满足性由基于语法的约束求解器检查。CSmith [19]生成覆盖了C的大部分子集的C程序,同时避免了可能破坏其查找错误能力的未定义和未指定行为。它从语法中随机选择允许的生产规则来生成C程序。LangFuzz [20]使用给定的语法从给定的语料库中学习代码片段(例如,一套先前失败的程序的测试)。然后,它重新组合提供的测试套件的片段以生成新程序,假设以前有问题的输入的重组很有可能导致新的崩溃。IFuzzer [21] 使用语言的上下文无关的 grammar 从给定的测试样本中提取代码片段。然后,它以生物进化的方式重新组合代码片段以生成新的样本。Radamsa [41] 自动构建一个 CFG,描述给定训练样本的结构,并使用 CFG 生成类似的数据进行稳健性测试。它在完全随机和手动测试设计之间取得了实际的平衡,并通过发现数百个错误被证明是非常有效的。
这些基于输入模型和基于语法的模糊测试方法 通常可以轻松传递语法解析,但通常无法通过检查输入语义有效性的语义检查。因此,从这些方法生成的输入中只有一小部分可以到达应用程序执行阶段, 而深度错误通常隐藏在该阶段。不同的是,通过直接将语义规则视为所提出的PCSG中的上下文,我们的方法生成的输入大多可以通过语义检查。
还有一些基于语法的模糊测试方法[22,23,24]使用硬编码或手动指定的生成规则来表达语义规则。mangleme[22]是一个自动损坏的HTML生成器和浏览器模糊器,最初用于查找所有主要Web浏览器中的数十个安全性和可靠性问题。]是最流行的模糊测试工具之一,在Mozilla JavaScript引擎中发现了1000多个bug。它使用有关过去和常见漏洞的特定知识以及硬编码规则来生成输入。Dewey等人[24]建议使用约束逻辑编程(CLP)来生成程序。使用 CLP,测试人员可以手动编写声明性谓词来指定有趣的程序功能,包括语法功能和语义行为。但是,这是令人生畏的劳动密集型,甚至不可能手动表达所需的语义规则。不同的是,我们建议直接从现有样本中学习这样的语义规则,并自动利用这些学到的知识来生成输入。

C. 模糊增强

已经提出了几种升压技术[6,42,43,44,45]来提高当前模糊测试方法的效率。
Householder和Foote [42]引入了一种基于机器学习的算法,用于选择两个模糊测试参数(即种子输入和种子输入的比例进行 突变),以最大限度地增加在模糊测试活动期间发现的独特应用程序错误的数量。与基本参数选择技术相比,它们大大提高了发现独特应用错误的效率。
Woo等人[43]根据经验研究了如何安排一组给定的程序种子对的模糊测试,以最大限度地增加发现的独特错误的数量。为此,他们构建了黑盒突变模糊测试的数学模型,并用它来评估26种现有的和新的随机在线调度算法。同样,Rebert等人[6]实证研究了如何挑选种子文件,以最大化在模糊运动中发现的错误总数。他们评估了六种不同的算法,并表明算法的选择可以大大增加发现的错误数量。他们还表明,桃子[15]中目前的种子选择策略可能并不比随机采摘种子更好。
Cha等人[44]提出了一种动态调整突变比率的算法,以便在给定程序和种子输入的情况下最大化黑盒突变模糊测试中发现的错误数量。他们利用对程序种子对执行跟踪的符号分析来检测输入位位置之间的依赖关系,然后使用此依赖关系来计算此程序种子对的概率最佳突变比。在相同的模糊处理时间内,结果比之前的三个模糊程序在八个程序中平均减少了38.6%的错误。
AFLFast [45]通过几种策略提升了AFL,将大部分模糊测试工作集中在低频路径上,以便在相同的模糊处理时间内探索更多path。在模糊测试期间,它选择i)执行较低频率路径的种子和ii)选择频率较低的种子,这允许尽早模糊处理最佳种子。
我们的种子生成方法将平面二进制文件格式的通用种子选择问题转换为自动生成方法,特别是对于具有某些语法结构的输入,并在一些经过传统approaches广泛模糊测试的程序上进行评估;另一方面,它也与这些技术正交,并且可以作为第一步链接在一起。我们计划将这些增强技术与我们的方法相结合,以研究是否可以进一步提高模糊测试效率。

七.结论

其他阅读参考论文阅读笔记 | Skyfire: Data-Driven Seed Generation for Fuzzing(S&P 2017)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值