浏览器模糊测试在Mozilla的应用
作者:Tyson Smith, Jesse Schwartzentruber, Sylvestre Ledru
日期:2021年5月20日
引言
Mozilla长期对Firefox及其底层组件进行模糊测试,这被证明是发现质量和安全问题最有效的方法之一。我们采用多层次的测试策略:既对完整浏览器进行测试,也通过libFuzzer等工具对独立代码(如JS引擎)进行专项测试。本文将聚焦浏览器级模糊测试,详细解析我们构建的自动化流水线。该流水线凝聚了团队多年经验,能持续生成可操作的漏洞报告,并整合内外部测试工具。
构建插桩技术
为实现高效错误检测,我们采用多种技术组合:
- 代码消毒工具:AddressSanitizer(含LeakSanitizer)、ThreadSanitizer、UndefinedBehaviorSanitizer
- 调试构建:启用运行时断言检查
- 调试工具:rr、Valgrind
- 代码覆盖率检测:为libFuzzer等工具提供支持
每种工具针对特定类型缺陷,但部分存在兼容性问题。不同操作系统和架构需要定制化构建,且需覆盖Release/Beta/Nightly/ESR等多个版本分支。
构建下载管理
通过Taskcluster获取最新测试版本时面临复杂挑战:构建变体×操作系统×架构的组合导致管理难度陡增。为此我们开发了fuzzfetch工具,它能:
- 按参数自动下载解压构建版本
- 支持指定版本号以配合二分法调试
- 简化多环境下的构建管理
测试用例生成
我们混合使用公开和自研的模糊测试器(如基于WebIDL的测试器)生成测试用例。具体技术细节可参阅《Fuzzing Firefox with WebIDL》及项目文档。
执行与规模化处理
Grizzly框架是浏览器测试的核心引擎,其功能包括:
- 并行运行多个测试实例
- 通过容器化封装测试配置(配置库托管于Orion仓库)
- 自动检测崩溃/挂起等异常
- 与FuzzManager服务集成实现自动报告
针对JS引擎等专项测试,我们采用libFuzzer接口;第三方库测试则通过OSS-Fuzz完成。
结果管理
海量测试数据通过分层系统处理:
- 客户端过滤:FuzzManager客户端库先剔除重复崩溃
- 服务端聚合:通过特征签名对报告分组
- 自动化精简:使用Grizzly Reduce和Lithium工具压缩测试用例(通常可移除90%冗余数据)
- 持续监控:定期生成代码覆盖率报告
高效漏洞报告
我们优化的报告包含:
- 崩溃日志与调用栈
- 构建环境信息
- 精简后的测试用例
- Pernosco调试会话记录
- 通过Bugmon自动二分法确定的回归范围
Grizzly Replay工具支持:
- 自动化复现测试用例
- 生成rr调试轨迹
- 处理不稳定测试场景
与Pernosco的结合使得偶现问题可被有效捕获——通过数千次重复运行获取有效轨迹,彻底改变了传统难以复现问题的处理方式。
开发者协作
沟通机制包括:
- 联系渠道:fuzzing@mozilla.com或Matrix聊天
- Bugzilla问题跟踪
- PrefPicker工具管理测试参数:建议新功能开发者将实验性参数加入模糊测试模板
- 分类处理"fuzz-blocker"类问题(虽不影响产品但阻碍测试覆盖)
成效评估
通过Bugzilla的meta-bug功能统计各测试器发现的问题(例如Domino测试器已发现1100+漏洞),并建立仪表盘量化投资回报率。
持续演进
测试流水线需要持续适配:
- 浏览器架构变更
- 新调试工具引入
- 功能模块的增删改
我们呼吁Firefox开发者:
- 及时告知需要测试的新功能
- 优先处理fuzz-blocker类问题
- 维护PrefPicker测试参数模板
安全研究人员可通过漏洞赏金计划参与测试,所有工具均已开源。