Mozilla的浏览器模糊测试

2021-02-10 03:21:38

Mozilla一直在模糊Firefox及其底层组件。它已被证明是识别质量和安全问题的最有效方法之一。通常,我们在不同级别上应用模糊测试:浏览器作为一个整体进行模糊测试,但也需要花费大量时间来对孤立的代码(例如使用libFuzzer)或整个组件(例如使用单独的外壳的JS引擎)进行模糊测试。在此博客文章中,我们将只讨论浏览器模糊问题,并详细介绍我们开发的管道。这条单一的管道是模糊测试团队经过多年努力的结果,聚集了我们的浏览器模糊测试工作,以向开发人员提供一致可行的问题,并在可用时简化内部和外部模糊工具的集成。

为了尽可能有效,我们使用了多种错误检测方法。这些工具包括诸如AddressSanitizer(带有LeakSanitizer),ThreadSanitizer和UndefinedBehaviorSanitizer之类的清理器,以及使用启用断言和其他运行时检查的调试版本。我们还使用了rr和Valgrind等调试器。这些工具中的每一个都提供了不同的视角来帮助发现特定的错误类型,但是许多工具彼此不兼容,或者需要使用自己的自定义版本才能发挥作用或提供最佳结果。除了提供调试和错误检测之外,某些工具如果没有构建工具也无法工作,例如代码覆盖率和libFuzzer。每个操作系统和体系结构的组合都需要唯一的构建,并且可能仅支持这些工具的一部分。

最后,每个变体都有多个活动分支,包括发行版,Beta版,每夜版和扩展支持版本(ESR)。 Firefox CI Taskcluster实例会定期构建每个实例。

Taskcluster使查找和下载最新版本进行测试变得容易。上面我们讨论了由不同仪器类型创建的变体的数量,我们需要对它们进行自动化模糊处理。由于构建,工件,体系结构,操作系统以及每个软件包的大量组合,因此下载是一项艰巨的任务。

为了帮助降低构建管理的复杂性,我们开发了一个名为fuzzfetch的工具。 Fuzzfetch使您可以轻松指定所需的构建参数,并将下载并解压缩该构建。它还支持下载指定的修订版,以使其可用于二等分工具。

由于此博文的目的是解释整个流程,因此我们不会花太多时间来解释模糊测试。如果您有兴趣,请阅读“使用WebIDL使Firefox模糊”和树状文档。我们结合使用公共可用的和定制的模糊测试器来生成测试用例。

对于针对浏览器的模糊器,Grizzly管理和运行测试用例并监视结果。创建适配器可以使我们轻松地在Grizzly中运行现有的模糊测试器。

为了充分利用任何给定机器上的可用资源,我们并行运行多个Grizzly实例。

对于每个模糊器,我们创建容器来封装运行它所需的配置。这些存在于Orion monorepo中。每个模糊器都有一个配置,该配置具有部署细节和资源分配,具体取决于模糊器的优先级。 Taskcluster持续部署这些配置以分配工作并管理模糊测试节点。

Grizzly Target处理诸如挂起,崩溃和其他缺陷之类的问题。目标是Grizzly与浏览器之间的接口。检测到的问题将自动打包并报告给FuzzManager服务器。 FuzzManager服务器提供自动化和用于对结果进行分类的UI。

其他更具针对性的模糊器使用JS Shell,基于libFuzzer的目标使用模糊接口。 OSS-Fuzz中也模糊了许多第三方库。这些值得一提,但不在本文讨论范围之内。

针对多个目标大规模运行多个模糊测试器会生成大量数据。这些崩溃不适用于直接进入Bugzilla等Bug跟踪系统。我们有工具来管理这些数据并准备报告。

FuzzManager客户端库可以过滤崩溃变化和重复结果,然后再离开模糊测试节点。唯一结果将报告给FuzzManager服务器。 FuzzManager Web界面允许创建签名,以帮助在存储桶中将报告分组在一起,以帮助客户端检测重复的结果。

模糊测试器通常会生成长达数百甚至数千行的测试用例。 FuzzManager存储桶将自动进行扫描,以在Taskcluster中进行队列减少任务。这些还原任务使用Grizzly Reduce和Lithium来应用不同的还原策略,通常会删除大多数不必要的数据。每个铲斗都会不断进行处理,直到成功完成还原。然后,工程师可以对最小化的测试用例进行最终检查,并将其附加到错误报告中。最终结果通常用作Firefox测试套件中的崩溃测试。

还定期测量模糊器的代码覆盖率。 FuzzManager再次用于收集代码覆盖率数据并生成覆盖率报告。

我们的目标是创建可行的错误报告,以尽快解决问题,同时最大程度地减少开发人员的开销。

Grizzly Replay是形成Bugmon和Grizzly Reduce的基本执行引擎的工具,它使收集rr痕迹提交到Pernosco变得容易。它使重新运行浏览器测试用例在自动化和手动使用方面都很容易。它简化了处理顽固的测试用例和触发多个结果的测试用例的工作。

如前所述,我们还一直在使用Pernosco。 Pernosco是一个为rr跟踪提供Web界面的工具,使开发人员可以使用它们,而无需直接访问执行环境。它是由同名公司开发的了不起的工具,可以极大地帮助调试大规模并行应用程序。当测试用例过于不可靠而无法减少或附加到错误报告时,它也非常有用。创建rr跟踪并上载它可以使停滞的错误报告具有可行性。

Grizzly和Pernosco的结合还具有使不经常发生,难以重现的问题变得可行的额外好处。一个非常不一致的问题的测试用例可以运行数百或数千次,直到在rr下发生所需的崩溃为止。跟踪将自动收集并准备提交给Pernosco并由开发人员修复,而不是因为无法执行而被传递。

要请求新功能获得适当的评估,可以通过[email protected]或通过Matrix与Fuzzing团队联系。这也是任何原因联系的好方法。我们很高兴为您提供任何令人困惑的相关问题或想法。当我们收到有关我们认为需要关注的新计划和功能的信息时,我们也会伸出援手。组件开始模糊化之后,我们主要通过Bugzilla进行通信。如前所述,我们努力解决可解决的问题或增强他人记录的现有问题。

Bugmon用于自动平分回归范围。这会尽快通知适当的人员,并在将错误标记为“已修复”后验证错误。关闭错误会自动将其从FuzzManager中删除,因此,如果类似的错误进入了代码库,则可以再次对其进行识别。

模糊测试期间发现的一些问题将阻止我们有效地模糊功能或构建变体。这些被称为模糊阻止程序,它们以几种不同的形式出现。从产品的角度来看,这些问题看起来似乎是无害的,但是它们可以阻止模糊测试程序针对重要的代码路径,甚至完全阻止目标模糊测试。适当地对这些问题进行优先级排序并快速将其修复是非常有用的,并且受到模糊测试团队的赞赏。

PrefPicker管理用于模糊测试的Firefox首选项集。在首选项之后添加功能时,请考虑将其添加到PrefPicker模糊模板中以在模糊期间启用它。对PrefPicker模糊模板的定期审核可以帮助确保不遗漏区域,并尽可能有效地利用资源。

与其他领域一样,衡量是评估成功的关键部分。我们利用Bugzilla的meta bug功能来帮助我们跟踪由模糊器识别的问题。我们努力使每个模糊器和每个模糊的新组件都有一个元错误。

例如,Domino的元错误列出了此工具标识的所有问题(超过1100个!)。使用此Bugzilla数据,我们可以显示多年来各种模糊测试的影响。

模糊测试管道中有许多组件。这些组件在不断发展,以适应调试工具,执行环境和浏览器内部的变化。开发人员总是在添加,删除和更新浏览器功能。正在检测,分类和记录错误。要使所有内容连续运行并针对尽可能多的代码,需要不断不断的努力。

如果您使用Firefox,可以通过使我们了解可能会影响或需要进行模糊检测的新功能和计划,对模糊阻止程序进行优先级排序以及在PrefPicker中整理模糊检测首选项来提供帮助。如果您对模糊测试感兴趣,请参加Bug赏金计划。我们的工具是公开可用的,我们鼓励寻找错误。