持续Fuzzing在DevSecOps中的应用

长期以来,一直有个疑问:

Fuzzing为何一直未被引入DevSecOps中?

刚好本周有两件事引起我的关注:

  1. Google发布CIFuzz以支持Github项目实现CI构建过程中的持续Fuzzing(Continuous Fuzzing)
  2. RSA创新沙盒比赛中ForAllSecure公司的参赛产品Mayhem——下一代Fuzzing解决方案

这两件事其实是往着同一目标前进的,就是将Fuzzing引入到CI持续集成中,直观的表现就是,当往代码仓库提交代码后,可被自动编译并完成Fuzzing,最后输出结果以进入下一开发环节。

这跟我去年11月在”天府杯”上分享的《Fuzzing平台建设的研究与设计》中的思路是类似的,当时国内外还没任何公开的产品,这次CIFuzz与Mayhem的出现,终于填补了这个空白。

先聊聊CIFuzz的实现原理

使用CIFuzz有2个要求:

1、只允许GitHub上的项目使用;

2、项目必须整合OSS-Fuzz

它主要利用GitHub Actions来实现下载、编译和运行oss-fuzz中的Fuzzer,若要fuzzing自己的项目,就得自己把先fuzzer提交到oss-fuzz。整个过程在docker中的ubuntu中运行,整个过程用workflow来定义这些操作行为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
name: CIFuzz
on: [pull_request]
jobs:
Fuzzing:
runs-on: ubuntu-latest
steps:
- name: Build Fuzzers
uses: google/oss-fuzz/infra/cifuzz/actions/build_fuzzers@master
with:
oss-fuzz-project-name: 'example'
dry-run: false
- name: Run Fuzzers
uses: google/oss-fuzz/infra/cifuzz/actions/run_fuzzers@master
with:
oss-fuzz-project-name: 'example'
fuzz-seconds: 600
dry-run: false
- name: Upload Crash
uses: actions/upload-artifact@v1
if: failure()
with:
name: artifacts
path: ./out/artifacts

所说GitHub 为每个 workflow 提供独享 1 核虚拟 CPU, 3.75GB 内存 和 100GB 的磁盘空间,提供相当慷慨的计算资源。对于想将Fuzzing引入CI中的DevSecOps建设,确实挺耗计算资源的。还有另一种方法,就是由开发本地提交代码时,自动完成Fuzzing后再提交,利用的是开发者本地的计算资源,对于Fuzzing平台建设是最节约成本的。

当发现崩溃后,会在前端输出崩溃的栈回溯和测试用例等关键信息:

artifacts

在腾讯内部,我们一般称workflow为流水线,在产品体验上这功能绝对秒杀GitHub,就是我之前贴着这张图:

img

再来看看Mayhem

对于Mayhem的信息是有限的,只有官网提供的相关文档。先来看下Mayhem的工作原理,大体流程跟上面一致的:

image-20200301195430422

它将符号执行与覆盖引导技术结合用于Fuzzing测试,但符号执行整体上是偏于理论,且难以用于大项目,因为它容易出现路径爆炸问题。虽然他们用来打过CGC机器人CTF比赛,但其赛题都是定制的,并不能完全代表真实的软件世界,这点还需要时间来考验。

image-20200301195624394

Mayhem提供有比较友好的前端界面,在功能上要比CIFuzz更加完善和自动化,体现出一个完整商业产品的特点:

img

image-20200301200249609

发现崩溃后,也能够提供更加详细的崩溃信息,包括重现方法、样本下载、崩溃指令和地址等等:

img

img

Continuous Fuzzing实现上的常见问题

个人对持续Fuzzing建设的一些思考总结,列举一些常见问题和解决方案,欢迎私信探讨。

1、如何设置Fuzzing时长,既能保证测试的有效性,又能保证CI流程的流畅,避免产品发布受阻?

以往Fuzzing跑个几天是很常规的姿势,最长的我也跑过几个月的,但这在CI中显然是不合适的,必须为此设置时长限制,Google CIFuzz是默认10分钟,但个人觉得太短了,最好是几小时,但这要结合业务场景来定,有些产品一天构建N次,这得浪费不少计算资源。如果资源有限的话,最好每天一款产品只能Fuzzing一次。

2、如何编写Fuzzer保证测试的有效性?

CIFuzz是自己提供Fuzzer,需要开发者基于libfuzzer编写的fuzzer;而Mayhem没有明说,但一般都得开发者或者安全人员来开发。这个问题之前我也在《Fuzzing平台建设研究与设计》中说过,可以培训开发用libfuzzer来写fuzzer,也可以直接写单元测试程序,以及安全人员作定制化的fuzzer。

3、如何保证Fuzzing执行时的服务器安全?

使用者提交自己的代码并编译执行,如果不作隔离,肯定就后门无数,沦为大家的肉鸡。使用docker作隔离的容器是已经很成熟的方案了,不仅fuzz,其它一些DevSecOps建设中的其它安全测试方案同样适用,比如CI中的代码审计,我们也是用docker来做的。

4、如何提供测试样本?

CIFuzz是自己在oss-fuzz中指定好的样本,Mayhem是明说,但估计也是需要用户提供。在之前的文章,有讲过我的实现思路:以后缀名来区分文件格式,自动爬虫收集,根据输入数据的格式自动提供,对于特殊的输入数据,需要自己另外去收集,比如hook收集等等。本质上,无非就是开发者提供测试数据,或者平台建设者提供各种常见格式的测试样本。

如果你对DevSecOps建设、漏洞挖掘感兴趣,欢迎私信。

终端安全工程师(深圳)

岗位职责:
1.安全评估:对公司内的移动终端产品进行安全评估,并提供自动化检测规则,探索与实践DevSecOps
2.代码审计:开发自动化的代码审计系统
3.应急响应。对外部报告的终端漏洞进行响应,分析漏洞,排查影响范围,并提供检测与防御方案;
4.业界追踪。保持关注业界最新安全动态、新安全技术及发展趋势,促进安全技术的提升;
5.沉淀培训:形成技术知识的沉淀和分享,开展公司内交流和培训工作。

岗位要求:
1.本科及以上学历;
2.2年以上的安全工作经验;
3.熟悉常见的终端安全风险的危害、原理及其防御方案;
4.熟悉x86和ARM汇编,熟练使用IDA、GDB等逆向分析与调试工具
5.熟悉主流语言的代码安全审计技术,具备⼈工审计与自动化审计系统开发能⼒
6.熟悉DevSecOps并且有参与过其中一些安全过程的技术和经验;
7.熟悉移动终端应⽤隐私合规检测技术
7.至少熟悉C/C++、Python、Java其中的⼀门语⾔,能够独立开发漏洞检测工具
8.具备较强的学习能力、动手能力、沟通能力、团队合作意识及综合分析能力;

具备优秀安全基础能力或某一领域深度安全能力并对安全有浓厚兴趣者优先;
有终端自动化审计系统开发经验者优先;
有代码审计系统开发经验者优先;
有知名软件的CVE漏洞发现与利用成果的优先。

WX20200229-165739