DeepState集成集成式模糊测试:多策略并发漏洞挖掘新突破

DeepState单元测试框架新增集成式模糊测试功能,支持多模糊测试器并发执行与种子同步,通过统一前端API简化工作流,提升真实场景下的漏洞发现效率与测试覆盖率。

DeepState 现已支持集成式模糊测试 - Trail of Bits 博客

Alan Cao, 纽约皇后区弗朗西斯·刘易斯高中
2019年9月3日
模糊测试, 实习项目

我们自豪地宣布将集成式模糊测试(ensemble fuzzing)功能集成至DeepState——这是我们基于模糊测试与符号执行的单元测试框架。集成式模糊测试允许测试人员在单次测试活动中执行多个采用不同启发式策略的模糊测试器,同时保持跨模糊测试器队列同步生成输入种子的架构。

这款全新的集成式模糊测试器包含新的deepstate-ensembler工具,以及多个由全新开源DeepState前端API/SDK驱动的知名模糊测试引擎。该SDK使开发者能够为DeepState集成前端执行器,并为我们的集成工具提供种子同步支持。

智能模糊测试器的误区

模糊测试器是安全研究人员工具箱中最有效的工具之一。近年来,为了构建更好的启发式方法或策略(即模糊测试器用于探索程序的方法),它们得到了广泛研究。然而,有一点仍然明确:模糊测试器的启发式方法很少能达到其宣传的效果。当将所谓的智能模糊测试器扩展到真实世界程序时,它们的性能常常不尽如人意,最终我们不得不回归到像AFL和LibFuzzer这样的“傻瓜式”标准工具。

由于我们过去曾探讨过评估模糊测试研究的主题,现在让我们换个角度,探索在不牺牲测试工作流时间的前提下,结合多种模糊测试器启发式方法以最大化模糊测试性能的可能性。这促成了我夏季实习项目的内容:将集成式模糊测试集成到DeepState中。

什么是集成式模糊测试?

集成式模糊测试的核心理念是:虽然某些启发式方法在特定情境下表现良好,但将它们组合起来应能产生比单一策略的单个模糊测试器更好的结果。这一想法最初由Chen等人的EnFuzz论文提出,但目前尚无开源或商业实现。

我们的集成式模糊测试器实现遵循EnFuzz中实施的架构,如下图所示:

给定一组预定义的多样化基础模糊测试器(各自具有本地种子队列),我们可以集成一个全局异步-本地同步(GALS)的种子同步机制,该机制在执行周期中将有趣的种子从本地队列拉取到共享的全局队列。因此,当基础模糊测试器的启发式方法无法提高覆盖率或发现有趣的输入种子时,它可以在下一个执行周期中从全局队列拉取其他模糊测试器的种子。此外,一旦测试活动终止,我们可以从集成器接收有关基础模糊测试器性能、崩溃分类/去重或任何其他后处理统计信息的模糊测试反馈。

通过使用集成式模糊测试和我们本就强大的用于模糊测试/符号执行的单元测试框架DeepState,我们能够在测试过程中解决以下问题:

  • 模糊测试器性能多样性——不同的模糊测试器启发式方法是否贡献了不同的有用种子,从而最大化提高覆盖率和发现崩溃的潜力?
  • 模糊测试器工作流——如何在简化工作流的同时进行详尽的模糊测试和/或符号执行?
  • 不变性一致性——不同的模糊测试器是否返回不同的结果,表明我们的测试中可能存在非确定性来源?

启动前端

由于DeepState已支持Eclipser作为后端,我们选择首先构建一个前端API,开发者可以为此编写模糊测试器后端的前端包装器。这可以协调运行的模糊测试器进程,并执行编译时插桩、前后处理以及种子同步。它还通过统一工具构建方式同时实现功能,简化了模糊测试环境设置。

以下代码片段展示了AFL前端包装器的示例。它继承自基础DeepStateFrontend类,并包含定义模糊测试器相关功能的方法。

1
# AFL前端包装器示例。一个继承的方法pre_exec允许用户在执行前执行完整性检查。检查环境属性(即核心转储模式)和参数解析。

为了构建前端包装器,我们的模糊测试器对象应包含以下方法:

每个模糊测试器都有自己的集成方法,该方法提供专门的rsync调用来从全局和本地队列目录推送和拉取种子:

1
# 用于种子同步的集成方法。每个__sync_seeds()调用都会调用专门的rsync命令在本地和全局队列目录之间传输种子。

构建完成后,我们可以这样使用前端包装器:

1
2
3
4
5
# 使用AFL插桩编译DeepState测试工具
$ deepstate-afl --compile_test MyDeepStateHarness.cpp --compiler_args=”-Isomelib/include -lsomelib -lotherlib”

# 通过DeepState执行AFL模糊测试器
$ deepstate-afl -i seeds -o out ./out.afl

有关模糊测试器前端API及如何实现自己的前端的更详细说明,请参阅本教程。DeepState目前已有AFL、libFuzzer、Angora、Eclipser和Honggfuzz的前端执行器。

查看演示

构建集成器

使用统一的API,我们现在可以构建一个集成式模糊测试器,该测试器配置前端对象并并发执行模糊测试器,同时保持种子同步。

首先,获取DeepState测试工具输入,并通过每个前端对象暴露的compile()调用,将多个插桩二进制文件“集成编译”到带有我们模糊测试器的工作空间目录。

1
# 使用“集成编译”策略配置带有二进制文件的测试工作空间。

完成后,每个并行模糊测试器进程通过run()实例化。由于每个前端包装器通过ensemble()调用rsync风格的同步,集成器只需在指定的同步周期(以秒为单位)后从每个前端调用它来同步种子。

该实现出奇地简单,仅用约300行Python代码构建。以下是在我们的测试示例之一Crash.cpp上运行集成器的快速演示。

全部模糊测试!

受Google的fuzzer-test-suite和前述模糊测试器性能测试工作的启发,我们认为一个由DeepState驱动的测试套件deepstate-test-suite,可以帮助进行模糊测试器性能A/B测试和实际的漏洞狩猎。借助我们易于使用的模糊测试器和集成器,让我们评估它们在实际测试用例基准上的表现!

大数(bignum)漏洞是一类特别有趣的错误,因为边缘情况更难发现,甚至具有概率性。这使得它们成为DeepState属性测试的理想目标。

我们为基础模糊测试器和集成器设定了基准,以评估它们在复现现有测试用例和真实世界大数漏洞(TweetNaCl中的进位传播错误)方面的性能。遵循这篇模糊测试评估论文中的评估方法,使用来自格式良好的初始输入的10个崩溃实例测量每个测试用例的平均时间:

这些结果提供了关于模糊测试器多样性的一些有趣见解。在较小的封闭测试用例(如Runlen示例)上运行更智能的模糊测试器(如Angora和Eclipser)效果很好。然而,当扩展到真实世界软件中的实际漏洞发现情境(如TweetNaCl错误)时,它们的性能下降。集成式模糊测试器的性能表明它能够很好地扩展以适应这两种测试用例。

集成式模糊测试的未来是什么?

集成式模糊测试是一种强大的技术,可扩展到真实世界的软件库和程序。将集成式模糊测试器集成到DeepState中,通过简化的工作流增强了单元测试的能力,并为许多其他研究和工程工作开辟了可能性。

根据我们当前的基准测试结果,我们不能肯定地说集成式模糊测试是最佳的模糊测试策略,但值得注意的是,在评估模糊测试器时总是存在随机性和概率行为的元素。有效的集成式模糊测试可能依赖于基础模糊测试器的选择——根据正在分析的目标类型或错误类别确定要调用哪些模糊测试器以及何时调用。

也许我们当前的模糊测试器集成在复现大数漏洞方面有效,但它们在其他类型的错误上也能同样有效吗?如果我们以特定顺序调用模糊测试器,是否会更加有效?这些问题可以通过对多样化目标进行更多基准测试来更准确地回答。

致谢!

在Trail of Bits担任安全工程实习生一直是一次美妙的经历。与优秀的员工和实习生合作真正推动了我对安全研究的理解,以及我们如何将深刻的学术研究转化为可工作的软件实现,就像我之前使用Manticore分析密码学原语的工作一样。我特别兴奋能在纽约大学继续这项工作,我将在春季开始在那里学习!

如果您喜欢这篇文章,请分享:
Twitter、LinkedIn、GitHub、Mastodon、Hacker News

comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计