Mozilla 自身是如何模糊 Firefox 浏览器的?
导语:Mozilla一直在模糊Firefox及其底层组件,它已被证明是识别质量和安全漏洞的最有效方法之一。
Mozilla一直在模糊Firefox及其底层组件,它已被证明是识别质量和安全漏洞的最有效方法之一。通常,研究人员会在不同级别上应用模糊测试:浏览器作为一个整体进行模糊测试,但也需要花费大量时间来对孤立的代码(例如使用libFuzzer)或整个组件(例如使用单独的外壳的JS引擎)进行模糊测试。在此文中,研究人员将只负责解释浏览器模糊漏洞,并详细介绍他们已经寻找到的方法。
构建工具
为了尽可能有效,研究人员使用了多种漏洞检测方法。这些包括清除器,如AddressSanitizer(带有LeakSanitizer)、ThreadSanitizer和UndefinedBehaviorSanitizer,以及使用调试构建来启用断言和其他运行时检查。研究人员还使用了像rr和Valgrind这样的调试器。这些工具中的每一个都提供了不同的视角来帮助发现特定的漏洞类型,但许多工具彼此不兼容,或者需要使用自己的自定义版本才能发挥作用或提供最佳结果。除了提供调试和漏洞检测外,一些工具如果没有构建工具就无法工作,例如代码覆盖率和libFuzzer。每个操作系统和体系结构组合都需要一个独特的构建,并且可能只支持这些工具的一个子集。
最后,每个变体都有多个活动变体,包括发行版,Beta版、nightly版本和延长支持版本(Extended Support Release, 简称“ESR”),Firefox CI Taskcluster实例会定期构建每个实例。所谓nightly版本,通常是开发者自己维护的一个版本。白天的时候开发者们将各自的修改提交到一个中心代码库,然后在晚上做一次编译得到的版本。一般来说nightly版本会包含最新的漏洞修改和新增功能,所以适合那些关注某个漏洞,或者是特别喜欢最新版本的用户使用。但是因为没有经过充分的测试,可能会有很多不稳定的地方。
下载版本
Taskcluster使得查找和下载最新版本进行测试变得很容易。研究人员在上面讨论了由不同的仪表类型创建的变体的数量,研究人员需要对它们进行自动化模糊处理。由于构建、工件、体系结构、操作系统以及每个软件包的大量组合,因此下载是一项艰巨的任务。
为了帮助降低构建管理的复杂性,研究人员开发了一个称为fuzzfetch的工具。Fuzzfetch可以很容易地指定所需的构建参数,并将下载并解压缩该构建。
如何生成测试用例
因为这篇博文的目的是解释整个流程,因此研究人员不会花太多时间来解释模糊测试,结合使用公共可用的和定制的模糊测试器来生成测试用例。
如何执行,报告和扩展
对于以浏览器为目标的模糊测试器, Grizzly管理和运行测试用例并监控结果,创建适配器可以使研究人员轻松地在Grizzly中运行现有的模糊测试器。Grizzly是一种应用程序框架,专门解决编写成千上万用户访问服务器时候产生的各种漏洞。
为了充分利用任何给定设备上的可用资源,研究人员并行运行多个Grizzly实例。
对于每个模糊测试器,研究人员都创建了容器来封装运行它所需的配置。这些都存在于Orion monorepo中。 什么是 Monorepo?Monorepo 其实不是一个新的概念,在软件工程领域,它已经有着十多年的历史了。概念上很好理解,就是把多个项目放在一个仓库里面,相对立的是传统的 MultiRepo 模式,即每个项目对应一个单独的仓库来分散管理。每个模糊测试器都有一个配置,根据该模糊测试器的优先级来配置具体的部署和资源分配。Taskcluster持续部署这些配置以分配工作并管理模糊测试节点。
Grizzly Target处理诸如挂起、崩溃和其他漏洞等漏洞的检测。Target是Grizzly和浏览器之间的接口。检测到的漏洞会自动打包并上报给FuzzManager服务器。FuzzManager服务器提供了自动化和筛选结果的UI。
其他更有针对性的模糊测试器使用JS shell和基于libFuzzer的目标使用模糊接口。许多第三方库在OSS-Fuzz中也被模糊化了,这些不在本文的讨论范围之内。
模糊测试结果
对不同的目标大规模运行多个模糊器会产生大量的数据,这些崩溃不适合直接输入到漏洞跟踪系统,比如Bugzilla。FuzzManager客户端库可以过滤崩溃变化和重复结果,然后再离开模糊测试节点。唯一结果将报告给FuzzManager服务器。通过FuzzManager的web界面,可以创建签名,将报表分组到存储桶中,帮助客户端检测重复的结果。
模糊测试器通常会生成长达数百甚至数千行的测试用例。 FuzzManager存储桶将自动进行扫描,以在Taskcluster中进行队列减少任务。这些还原任务使用Grizzly Reduce和Lithium来应用不同的还原策略,通常会删除大多数不必要的数据。每个存储桶都将持续进行处理,直到成功完成还原操作为止。然后,工程师可以对最小化的测试用例进行最终检查,并将其附加到漏洞报告中。最终结果通常用作Firefox测试套件中的崩溃测试。测试过程请点此查看。还定期测量模糊器的代码覆盖率,再次使用FuzzManager收集代码覆盖率数据并生成覆盖率报告。
漏洞报告
由于研究人员的目标是创建可操作的漏洞报告,以尽快修复漏洞,同时最小化开发人员的开销。
研究人员通过以下方式做到这一点:
崩溃信息,例如日志和堆栈跟踪;
建设和环境信息;
减少测试用例;
回归范围(通过Bugmon分割);
通过Bugmon进行验证;
Grizzly Replay是形成Bugmon和Grizzly Reduce的基本执行引擎的工具,它使收集rr痕迹提交到Pernosco变得容易。它使重新运行浏览器测试用例在自动化和手动使用方面都很容易。
如前所述,研究人员也一直在使用Pernosco。Pernosco是一个为rr跟踪提供web界面的工具,使开发人员无需直接访问执行环境就可以使用它们。这是一个由同名公司开发的工具,可以极大地帮助调试大规模并行应用程序。当测试用例太不可靠而无法减少或附加到漏洞报告时,它也非常有用。创建一个rr跟踪并上传它可以使不再使用的漏洞报告具有可操作性。
Grizzly和Pernosco的合并带来了一个额外的好处,那就是使不常见的、难以重现的漏洞变得可行。一个非常不一致的漏洞的测试用例可以运行数百或数千次,直到在rr下发生所需的崩溃为止。跟踪被自动收集并准备提交给Pernosco并由开发人员修复,而不是因为它不可操作而被忽略。
要对新特性进行适当的评估,可以通过fuzzing@mozilla.com或通过Matrix联系。一旦开始对组件进行模糊测试,研究人员将主要通过Bugzilla进行通信。如前所述,研究人员努力解决可修复的漏洞。
Bugmon用于自动将回归范围平分为两部分,并尽快通知适当的人员,并在将漏洞标记为“已修复”后进行验证。关闭漏洞会自动将其从FuzzManager中删除,因此,如果在代码库中找到类似的漏洞,则可以再次对其进行识别。
模糊测试期间发现的一些漏洞将阻止研究人员有效地模糊功能或构建变体,这些被称为模糊阻止程序,它们以几种不同的形式出现。从产品的角度来看,这些漏洞看起来似乎是无害的,但是它们可以阻止模糊测试程序针对重要的代码路径,甚至完全阻止模糊测试目标。适当地对这些漏洞进行优先级排序并快速将其修复是非常有用的。
PrefPicker管理用于模糊测试的Firefox首选项集。在首选项之后添加功能时,请考虑将其添加到PrefPicker模糊模板中,以便在模糊过程中启用它。对PrefPicker模糊模板的定期审核可以帮助确保不遗漏区域,并尽可能有效地利用资源。
与其他领域一样,衡量是评估成功的关键部分。研究人员利用Bugzilla的meta bug功能来帮助跟踪由模糊器识别的漏洞。研究人员努力使每个模糊器和每个模糊的新组件都有一个meta bug。
例如,Domino的meta bug列出了该工具标识的所有漏洞(超过1100个)。使使用此Bugzilla数据,研究人员可以显示多年来各种模糊测试的影响。
模糊测中有许多组件, 这些组件在不断发展,以适应调试工具、执行环境和浏览器内部的变化。 开发人员总是在添加、删除和更新浏览器功能。
发表评论