持续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

用afl玩超级玛丽:通过Fuzzing探索程序空间状态以发现更多执行路径

今年S&P顶会上有一篇研究论文“IJON: Exploring Deep State Spaces via Fuzzing”,他们通过改造AFL来探测程序的空间状态,以发现更多程序行为,并拿游戏”超级玛丽”来作演示:

当前最流行的Fuzzing技术就是基于覆盖率的方法,Edge Coverage应该是当前最有效的覆盖率统计方法,比BasicBlock方式多记录调用边界,而afl对覆盖率的探测很多是暴力猜解的,一些afl家族工具也对其进行扩展,比如切割多字节指令为单字节作数据比较,提取cmp指令的一些常量操作值作变异。但是,这种方法对于一些特定的代码结构,若不去探测程序状态空间的中间点,就很难触发新的覆盖路径。

何为程序状态空间?

状态空间代表程序所有可能状态的集合,状态代表内存和寄存器的一种配置,以及系统提供的状态(比如文件描述符、类似原语)。状态空间比代码覆盖统计空间更大,若改造AFL就需要实现对状态空间的支持,以优化测试用例达到状态的多样性。

论文主要贡献

  1. 分析当前主流Fuzzer的反馈机制,并实现如何用它们表示状态空间;
  2. 扩展当前主流的覆盖反馈Fuzzer的能力,允许分析人员通过程序状态空间解决当前业界方法无法解决的路径约束问题;
  3. 展示了可信平台模块(TPM)、复杂格式解析器、超级马里奥游戏、迷宫和散列映射实现的软件仿真器的状态空间,演示其是如何被Fuzzer有效探索到的。顺便,解决掉一些CGC挑战集合中的难题(CGC专门为机器人自动打CTF而设计的题目,与真实软件场景还是有差异的),也发现了一些真实软件的漏洞(其实就是一个偏门的dmg2img工具而已)。

主要设计原理

作者设计了一套源码注释原语,其实就是给源码加个一两行补丁代码,用来干预Fuzzer的反馈功能。在可交互的Fuzzing会话中,分析人员可以人工介入去分析一直无法触达的执行路径,然后为其增加补丁代码解决路径探索障碍的问题。

afl-gcc或afl-clang本身就是对gcc/clang编译器的封装,添加一些编译选项,以及代码插桩的功能,作者为其编写了个链接库,以实现前面所说的注释原语,包括一些自定义函数和宏等,通过它能够访问AFL用于存储覆盖信息的位图(其实是个哈希表),直接添加和设置条目上去,将状态值直接反馈给Fuzzer。同时,也允许相同的edge coverage存储到不同的覆盖位图中,因为不同的状态值可能触发的是同一处edge coverage,这代表它能够实现更细粒度的反馈,为此它还提供扩展用于存储覆盖位置的共享内存区域。对于状态空间爆炸的问题,也会提供”爬山算法”(hill-climbing)作出优化选择。

作者对超级玛丽作了修改,使所有的键盘命令都可以从标准输入中读取,并且马里奥只能不停地向右跑,只要停下来就死掉,这个设计主要是为节省时间。

作者还用改造后的Ijon与AFL作对比,运行12小时的AFL看其能打到哪一关,而使用注释原语的Ijon只几分钟就通过了大部分的关卡,有些确实过不了。下图是超级玛丽打喷火怪兽那关,线条是Fuzzer发现的所有执行路径,对比还是比较明显的,AFL暴力探测的密集度比较明显,更关键还是没通关,至少从作者统计图上看是如此的。

image-20200229151836427

论文链接:https://www.syssec.ruhr-uni-bochum.de/media/emma/veroeffentlichungen/2020/02/27/IJON-Oakland20.pdf

WX20200229-165739

从研究者的视角看Fuzzing技术发展30年

源起

1988年,在威斯康星大学Barton Miller教授的计算机实验课上(http://pages.cs.wisc.edu/~bart/fuzz/CS736-Projects-f1988.pdf ),首次提出Fuzz生成器(Fuzz Generator)的概念,用于测试Unix程序的健壮性,即用随机数据来测试程序直至崩溃。因此,Barton Miller教授也被多数人尊称为”模糊测试之父”。但是,当时更多是为了验证代码质量和程序的稳定性,而非专门用于挖掘安全漏洞,真正用于软件安全漏洞挖掘的开端要从下面两件事说起。

从学术界到工业界的证明

2001年,芬兰奥卢大学公布PROTOS测试集项目的研究成果(https://rd.springer.com/content/pdf/10.1007%2F978-0-387-35413-2_16.pdf ),首次将Fuzzing技术应用在网络协议的安全测试当中,他们针对不同的网络协议构造出不同的测试用例集,这些在其官网(https://www.ee.oulu.fi/research/ouspg/Protos )上依然可以下载到。2002年,PROTOS逐渐成熟,Microsoft开始为该项目提供资金支持。于是,2003年项目组成立了Codenomicon公司,开始将Fuzzing技术应用于商业产品,也确实发现了不少安全问题。因此,PROTOS项目可以说是Fuzzing技术发展历程中的一次重要里程碑。可能大家对Codenomicon公司不太了解,但说到”心脏滴血”漏洞,应该无人不知无人不晓。没错,它就是Codenomicon公司发现的。

2002年,在BlackHat USA黑客大会上,来自Immunity安全公司(PS:还有人记得Immunity Debugger吗?)的Dave Aitel发表议题“An Introduction to SPIKE, the Fuzzer Creation Kit”,至此著名的Fuzzer工具SPIKE公布了,它是基于块模板定义的网络协议测试工具,优点是支持定义可变长度数据块的能力,除生成随机数据外,它还提供一些现成的边界值生成,以提供触发崩溃的概率。SPIKE的诞生,使得广大用户能够依据自身需求定制网络协议Fuzzer,这对Fuzzing技术的普及起到巨大的推动作用。早些年,笔者也曾写过一篇SPIKE的教程“基于SPIKE的网络协议Fuzzing技术(http://riusksk.me/2011/12/30/spike-fuzz/)",但现在其实基本不用了。

PROTOSSPIKE的诞生,代表着学术界与工业界对Fuzzing技术在商业与安全实战领域的应用提供了有力的证明。

文件Fuzzing技术的兴起

2004年,Peach模糊测试框架的发布,标志着文件Fuzzing时代的到来。最初Peach是用Python开发的,后来在2007年被收购后改用C#重写,并分为社区版和付费版。Peach支持文件格式、网络协议、ActivieX控件等多种形式,通过编写pit文件(xml格式)来定义数据格式,每次开始写的时候其实挺费劲的,后来有人提供自动将010editor格式解析器(仿C语言的bt文件)转换为pit,在一定程度上可以缓解劳动力。笔者第一次通过文件Fuzzing挖到漏洞也是借助Peach实现的。

直至今日,Peach依然还有人在用,更有人将PeachAFL打通,在Github上发布aflsmart的开源项目。

文件Fuzzing应该是当前Fuzzing应用中最为普遍的形式,即使是网络协议等其它目标的Fuzzing,也是可以转换为文件Fuzzing的。比如OpenSSL网络协议Fuzzing,通过源码打Log的方式先收集网络数据为本地文件,再调用其API写个hareness用AFL或libfuzzer进行本地测试,就顺利地将网络协议Fuzzing转换为文件Fuzzing。

语法模板Fuzzing:打开攻击浏览器的大门

2008年,Mozilla安全团队发布了jsfunfuzzDOMfuzz,基于JS语法模板来生成测试用例,以挖掘浏览器漏洞,后来两款工具合称funfuzz( https://github.com/MozillaSecurity/funfuzz ),以开源的形式对外公开。这款工具在当时确实挖到了不少浏览器的漏洞,但其语法模板的可扩展性并不友好,只能在其代码上作修改,这点不如dharma( https://github.com/MozillaSecurity/dharma ),以及后来Project Zero发布的Domato( https://github.com/googleprojectzero/domato )。这种基于语法模板的Fuzzing方式,挖完一波后,就要求保持模板的更新才能持续产出,同时要理解测试目标在JS代码上的触发逻辑,比如JIT可通过for循环来触发代码优化,Dom UAF可通过创建Dom元素,并调用相关元素的方法来触发删除和引用,以探测是否存在UAF的可能。整体上依赖于对语法和目标原理的理解,才能构造出好的语法模板。

funfuzz之后,业界也出现了好多款优秀的JS语法Fuzzing工具,比如grinderndujacrossfuzz等等。当年PC流行时代,用grinder来Fuzzing Windows IE浏览器的人应该比较多。

浏览器一直是网络攻击中最受关注和最常用的入口,过去如是,现今依然。因为系统自带,且用户使用率高,又是远程访问的最佳途径。渲染引擎和JS引擎一直是浏览器主要攻击面,主要以html、js、vbs作为解析语言,因此对这些语言的语法Fuzzing就自然而然的产生了。除此之外,如今WebSQL也开始备受关注,比如Chrome上的sqlite模块,SQL语法的fuzzing也随之而来。

除了浏览器,pdf的JS和flash的as语法解析,也一度作为攻击Adobe Reader和Adobe Flash的入口。

符号执行:学术与工业之争

2008年,基于LLVM的符号执行引擎KLEE发布后,引领了一波程序分析新姿势的潮流。后来,符号执行被应用于Fuzzing中,经常被用来打CTF比赛,用来找key、解混淆、fuzzing等用途。比如,将AFLangr结合的drillerhttps://github.com/shellphish/driller ),还被用在了CGC(Cyber Grand Challenge)自动网络攻防竞赛上,但这种比赛都是特定场景下的比赛,不能完全代表真实的软件世界;还有,将AFL与KLEE结合的kleeflhttps://github.com/julieeen/kleefl ),这款工具知道的人应该不多。

符号执行在学术界中应用得比较多,工业界相对少一些,这是现状。将符号执行应用在Fuzzing中,通过约束求解新路径的条件值,以增加代码覆盖率,可以一定程度上弥补暴力变异的不足。符号执行主要的挑战在于路径爆炸问题,约束求解能力的局限性,以及性能消耗问题,比如内存和时间消耗过大。符号执行与约束求解对于小型应用比较有效果,也常被用于CTF比赛,在CTF中使用最广的当属angr框架。但是,基于当前的业界情况,符号执行仍然比较难以应用于大型软件中。符号执行在Fuzzing中的应用并没有真正带来新的技术浪潮,真正的技术浪潮始于代码覆盖引导技术的引入。

代码覆盖引导技术:Fuzzing技术的分水岭

2013年底,afl-fuzzhttp://lcamtuf.coredump.cx/afl/ )发布了,首次采用源码编译插桩和QEMU模式来实现代码覆盖引导Fuzzing的方式,这绝对是Fuzzing技术发展历程中最重要的一次里程碑,也是技术分水岭,它开启了Fuzzing技术的新篇章。刚发布的时候,afl并没有那么火,主要是在2014和2015年期间,被很多人使用后挖到不少主流开源软件的0day,并在Twitter上宣传,使得更多人关注到并使用,这证明了代码覆盖引导技术在Fuzzing实战中的价值。

随后,基于afl二次开发的fuzzer如雨后春笋般涌现出来,比如winafl、libfuzzer、AFLFast、Vuzzer等等,而且针对各种语言的版本出相继出现,比如go、python、js、ruby等等。一些已知名的Fuzzer也迅速跟进,比如syzkaller内核Fuzzer,它原本是基于API调用模板的,后来也引入了代码覆盖引导能力。同时,业界都在试图将其移植到各种平台上(比如windows、android、IOT平台等等),并实现支持闭源程序的代码覆盖引导能力,这一直是近几年来Fuzzing技术研究的热点方向,比如动静态插桩、虚拟机模拟执行、硬件特性等等。无论是工业界大会(BlackHat、OffensiveCon、CCC等等),还是学术界四大顶会,关于Fuzzing的议题也越来越多,相信这种趋势会持续下去。

系统函数调用模板Fuzzing一度成为攻击内核的常用手段

2015年Google开源了syzkaller,一款用于Fuzzing Linux内核的工具,漏洞产出特别高。现在依然很多人用它来挖各系统平台的内核漏洞,包括Android、macOS、Windows等主流系统平台。syzkaller通过定义系统函数调用模板来实现,在模板中定义系统调用函数参数类型,并解决函数调用的顺序依赖和值依赖问题。Project Zero官方博客就曾写过一篇利用syzkaller fuzz socket挖掘Linux内核漏洞的文章,叫“Exploiting the Linux kernel via packet sockets(syzkaller usage)” ( https://googleprojectzero.blogspot.com/2017/05/exploiting-linux-kernel-via-packet.html ),详细讲述了如何编写模板,以及syzkaller的使用方式。

Windows平台也常被通过构建GUI API调用模板来Fuzzing系统内核,macOS平台内核Fuzzing就常拿IOKit函数开刀,都是基于这种系统函数调用模板的Fuzzing方式实现的。

2016年Google提出”结构感知型Fuzzing”(Structure-Aware Fuzzing ),并基于libfuzzerprotobuf实现了libprotobuf-mutator(https://github.com/google/libprotobuf-mutator),其实现思路与syskaller相似,它弥补了peach的无覆盖引导的问题,也弥补了afllibfuzzer对于复杂输入类型的低效变异问题。正如前面提到的,也有人将aflpeach整合成aflsmart,以此实现类似功能。现在Project Zero也用libprotobuf-mutator来fuzzing iOS内核,详见“SockPuppet: A Walkthrough of a Kernel Exploit for iOS 12.4”(https://googleprojectzero.blogspot.com/2019/12/sockpuppet-walkthrough-of-kernel.html)。

结构感知型Fuzzing并不是什么新技术,跟Peach的实现思路是一样的,只是对输入数据类型作模板定义,以提高变异的准确率。只是当前大家更倾向于将结构感知与覆盖引导等多种技术优势整合一块,基于系统函数模板用于Fuzzing系统内核,相信这种方式未来仍会被经常使用。

助力开源生态安全建设

在工业界中,最知名的Fuzzing平台当属Google的clusterfuzzhttps://github.com/google/clusterfuzz ),运行在25000+台机器上,发现过16000+个Chrome bug,11000+开源项目bug,这个平台整合了OSS-Fuzz(https://github.com/google/oss-fuzz ),既支持libfuzzer和AFL的代码覆盖引导Fuzzing,也支持黑盒Fuzzing。OSS-Fuzzclusterfuzz分别在2016年和2019年开源对外,业界同行可以协同开发,对于提交fuzzer后挖到新漏洞的,Google会美刀奖励提交者,对于主流开源项目的0Day,Google也是有奖励机制的。同时,Google开发了ASanMSanTSanUBSanLSan等多种编译时插桩工具用来帮助检测漏洞,有些漏洞只在开启相关Sanitizer之后才会触发异常,跟在Windows下开启页堆的方式类似,可以帮助更有效地发现崩溃场景,在发现和分析漏洞上提供帮助。

Google对开源生态安全建设的贡献,是各大互联网公司不能比的。他们的贡献不仅帮助提高各大主流开源项目的安全性,也降低了Fuzzing的技术成本,在资金和技术上对开源生态安全的建设提供了大力支持。

语法树变异成为语法解析引擎漏洞挖掘的新方向

2012年,USENIX安全顶会上发布一篇论文“Fuzzing with code fragments”,研究者开发了一款叫LangFuzz的工具,他们从firefox、webkit、chromium等开源的浏览器项目以及网络上去收集js测试样本,然后用ANTLR其进行AST语法树分析,再将样本拆分成非终止语法的代码片断,放入代码池中,最后再基于代码池的代码片断对输入样本作交叉变异,主要取同类型的代码片断作替换或插入,再运行生成的变异样本进行测试。

基于LangFuzz的思路,后面又有人开源了IFuzzer,并发表相关论文公开,在LangFuzz的基础上增加遗传算法,对输入样本进行评估,筛选出优秀的个体进行组装以产生新样本。不过这个工具并没有那么完善,也未见到比较好的实际漏洞产出。

2018年,Project Zero的Samuel Groß发布一款叫fuzzilli的JS语法Fuzzer工具,它整合了语法变异、模板生成、覆盖引导等多种技术,使用自定义中间语言用于语法变异,再将变异后的中间语言转换成JS代码。fuzzilli在3大主流JS引擎的测试中,战果颇丰,发现了不少漏洞,也因此被业界同行拿去作二次开发,又发现了其它新的漏洞。

2019年,有2篇学术论文发布,他们都引用了论文“Fuzzing with code fragments”中的思想,它们分别是”CodeAlchemist: Semantics-Aware Code Generation to Find Vulnerabilities in JavaScript Engines“和”Superion: Grammar-Aware Greybox Fuzzing“,CodeAlchemist将输入样本进行语法树分析和数据流分析,为拆分出来的代码片段设置前置和后置的约束条件,前置条件代表一些引用的变量需要先定义,后置条件代表代码片段的输出结果,通过两者来解决一些未定义变量引用的问题。Superion是将语法树变异规则置入AFL中实现的,借助AFL筛选变异后的输入样本,而且支持多种语言,也是采用ANTLR作语法树分析,其在语法扩展上比较友好。两款工具均在最新JS解析引擎上发现过若干0day漏洞,并且均已在Github上开源。

除了传统的模板Fuzzing,语法变异(无论是AST,还是自定义中间语言)也是一项值得探索的方向。

人工智能在Fuzzing中的应用仍亟待探索

2018年是人工智能元年,很多领域都在探索AI的应用,漏洞挖掘领域亦然。之前笔者阅读过一些AI应用在Fuzzing中的相关议题,主要集中在测试样本生成的训练上,利用已知漏洞的样本或正常样本作训练,然后重新生成测试样本进行测试。可惜从效果上来看,是一种高投入低产出的事情,有些还不如直接暴力变异来得高效高产。但这也不是说,AI没有价值,只是它在这方面的发展时间较短,很多东西仍亟待探索,还有待时间的年轮来证明。

Fuzzing平台建设的研究与设计(paper)

引言

近年来,无论是工业界,还是学术界,Fuzzing技术的应用都非常广泛。每年的BlackHat、OffensiveCon、CCC等工业界顶会,以及学术界四大顶会( S&P、CCS、Security、NDSS ),经常可以见到Fuzzing相关议题。Google Project Zero也公布其近5年的漏洞挖掘方式占比,其中Fuzzing占比37.2%,手工占比54.2%,其它占比8.6%,这对于高产的P0来说,37.2%的占比已经意味着不少漏洞了。按Project Zero官方公布的bug列表来看,当前共有1975个漏洞公开(包括一些无效、未修复的,这里仅作粗略估算),按37.2%来算,大约有735个漏洞是通过Fuzzing挖掘到的,着实不少的数量,况且大多是高质量漏洞。所以说,Fuzzing依然是当前安全界所热衷的漏洞挖掘方式。

本文主要探讨下企业内部关于Fuzzing平台建设的一些想法,个人主要是想表达一个观点:协同Fuzzing,即整合企业内部各工种(开发、测试、安全、运维等等)的力量,将Fuzzing合入CI构建中,通过DevSecOps协同模式来完成产品的Fuzzing工作,以便将漏洞消除在上线前阶段。

Fuzzing平台的价值思考

虽说Project Zero超过一半是人工审计发现的,但对于企业内部,项目之多,代码语言和代码行也是非常之多,很难单纯靠人工来解决的。量级的变化,自然会导致自动化需求的诞生,才能更加高效地发现、消除和监管企业内部的代码风险。

产品从开发到发布,涉及到多工种协作,如果能让他们一块参与到安全工作当中,那么有时也可以弥补安全人力的不足,同时让非安全出身的业余选手也能干专业的事,帮助安全人员覆盖更多的攻击面测试,提升漏洞发现率。

安全人员参与到产品的整个研发流程当中,可以将发现漏洞的时间线提前,有助于在产品上线前发现并解决安全风险,提高产品安全性。

协同Fuzzing平台的设计思路

1578971205508

以往我们在帮业务产品作安全测试时,开始前业务同事会提供文档资料或者开会分享产品功能设计的方方面面,以及担心的安全风险问题,安全同事需要花时间消化,前期双方都需要消耗不少时间成本,况且在有限的时间内,对产品的攻击面剖析也不一定足够到位。

假设当前需要对产品进行Fuzzing测试,一般需要一个支持命令行的测试程序,通常称为harness。开发或者测试的同学可能本身就会开发有相应的测试程序,如果没有,安全测试人员就得自己开发,有API或者源码都好办,没有的话,可能还得做Hook。

对产品最了解的,一般当属开发同学。所以,如果开发者在开发完相应功能后,开发以及质量测试人员若能够编写相应的接口测试程序,将对于安全测试会有很大帮助。一方面是工作效率的提升,另一方面是测试面的覆盖广度提升。

如此之后,我们可以设计出协同Fuzzing平台的工作流水线:

  1. 开发阶段:开发人员编写相应的harness程序,尽可能覆盖用于解析外部数据的处理函数。直接开发或者使用libfuzzer等安全测试库进行开发均可,安全人员也可定期对其进行安全培训,指导libfuzzer等工具的使用。
  2. 构建阶段:对于源码编译场景,支持多种构建触发方式,最佳的方式还是基于git事件触发,即提交代码后触发,然后将源码下载到指定的构建机编译,开发者需要配置编译命令,此处也可以开启ASAN或者AFL编译等功能;对于非编译场景,则直接提供相应的可执行程序下载地址,将其归档打包至用于Fuzzing的服务器上。目前,“腾讯CI”已将构建功能嵌入到自家git平台“工蜂”上,提供覆盖所有主流编译工具和语言,因此未来其在安全领域上的应用还有发挥的空间。
  3. 测试阶段:配置相应的测试命令,即harness程序的参数,以及运行环境,包括Windows、Linux、macOS,如果硬件资源丰富的话,Android和iOS又何尝不可。提交在服务器上布署好常见Fuzzer工具(afl/libfuzzer/honggfuzz等等),或者自主开发的其它Fuzzer,同时部署一些常见文件格式的样本库。对于特殊数据格式,比如自定义协议/文件格式,最好由开发或测试同学提供,否则只能安全测试人员去解决,一些提取样本数据的方法后面会介绍。
  4. 告警阶段:若发现崩溃,则作二次运行确认,确认二次崩溃则告警出来,可邮件、工单、微信等多种方式,将运行命令参数、崩溃场景的栈回溯、可利用性分析等基本信息同步出来。对于崩溃容忍度较低的产品,可设置“质量红线”,去重后的崩溃数量超过多少个禁止发布。开发修复漏洞后,继续从第一步的开发阶段开始继续循环下去,直至无新漏洞发现。

Fuzzing三要素

Github上已有很多知名Fuzzer被开源,圈内也有不少人借此挖到漏洞,直接基于现成工具,或者二次开发挖到的都有,也有人借鉴思路自主开发新的工具。对于一款新漏洞挖掘工具的发布,多数人可能会认为,开源作者应该是已经挖完漏洞了才公布的,应该已经挖不到0day了。但有时,你又会发现,老树开新花的事情还是很常见的。那么决定Fuzzer能否挖到漏洞的关键因素有哪些?根据个人经验,笔者觉得主要有三要素:目标、策略、样本

目标:攻击面分析

对于企业内部产品的测试,直接找开发要设计文档,甚至源码,都可以帮我们快速分析出攻击面。面对黑盒测试时,尤其是主流软件/系统的Fuzzing测试时,能够让我们参考的主要还是其官方文档,比如MSDN、Apple开发文档、Acrobat Javascript API手册等等。当初winafl诞生时,从MSDN找API去Fuzzing的方式屡试不爽,运气好的,一个API拿10个CVE也不是没干过;Apple开发文档中的系统的各个模块介绍,github上的示例代码等等,无不成为寻找攻击面的最佳途径;还有Acrobat 一个JS API产生好几个漏洞的情况,也有人直接写脚本分析API手册,提取API模板作Fuzzing;其它系统平台上写爬虫提取系统函数原型模板,作驱动Fuzzing。

这些从官方手册,以及官方放置在Github的示例代码,无不成为最佳的目标攻击面分析途径。如果你搞过上面这些,应该明白我在说什么。

除了文档,一些业界公开的漏洞信息,比如Project Zero、ZDI、厂商的补丁公告等等都是挖洞方向标。在以上信息都缺失的情况,就只能人工逆向分析来寻找攻击面了。

比如2019年微软的一次补丁公告中,出现了很多Jet数据库引擎的远程代码执行漏洞:

1578992349658

于是从MSDN入手去寻找可能存在的攻击面,然后用手上的Fuzzer框架进行Fuzzing,几小时之后直接挖到一个品相极佳的漏洞,因为生成的poc直接控制了EIP:

1578992386112

策略:变异之法

常见的变异策略主要有以下几种:

  1. 基于暴力:随机数据替换、插入、删除、数值增减、边界值替换、拷贝覆盖等等,比如radamsa等;
  2. 基于模板:文件格式、协议格式、API原型模板、语法模板变异等等,比如peach、domato等;
  3. 基于代码覆盖引导:通过提高代码路径的反馈方式来优化样本,比如AFL、Libfuzzer等等;
  4. 基于语法树变异:通过AST语法树变异来Fuzzing语法解析引擎,比如Fuzzilli,该工具本身也实现基于模板和代码覆盖引导的功能。

除了以上常规的变异方法之外,有时需要针对当前的应急漏洞作新变异规则,或者适配特定的业务场景作定制化,这就要求我们的Fuzzer平台具备可扩展的变异策略插件开发,这种方式不仅可以社区化方式协同,企业内部也可以协同开发,类似oss-fuzz。

举个案例,2018年word公式编辑器开始流行起来,还被在野利用过。当时笔者就用python开发个针对OLE中“Equation Native” 的变异器,然后用riufuzz跑起来(riufuzz是笔者基于honggfuzz二次开发的fuzzer,2018及之前的新功能已在github上开源,之后开发就未开源了,大家可以自行发挥):

1578992857498

有时在变异前、变异后可能有特列的处理机制需要处理,比如pdf js fuzz,输入pdf可能得提取js再作变异,这是变异前处理;再比如png图片变异,变异后会导致crc校验失效,需要作变异后修复。还有对于复合文档中的某特定格式的文件变异后,需要重组打包,比如变异docx中的图片、pdf中的字体图片等等,此过程注意后缀名的变更问题。

样本的收集与筛选

1578993191152

以前笔者都是手工去网上找样本去下载那种包含很多文件的压缩包,但这种方式太费劲了,用过想再更新又得再去找。后来就干脆用scrapy写个爬虫去搜索引擎搜索,像pdf、office文档、图片几乎都是爬不尽的,但它支持的文件格式比较有限。因此,我就改去Github爬虫,很多开发者在开发时,也需要一些测试样本来验证,因此项目内经常包含有各种文件格式的样本,但它的搜索结果只有100页,需要变换关键词(字典库、单词库、输入法词库等等)来搜索,但整体搜索到的数量还是没有Google等搜索引擎多,可以当作互补方案。

若是遇到如openssl这种特殊协议数据,以及其它非完整文件格式的自定义格式,一般就得通过源码加Log,或者Hook技术去dump出二进制流样本数据,以此作为输入样本。

当我们获取的样本过多时,就需要作筛选,以避免过多的无用测试。对于开源项目,用AFL的工具足矣,但闭源程序就需要自己实现,以下就是笔者基于pin开发的语料库蒸馏器,用C++和Python开发的,支持跨平台:

1578993681237

以macOS上的pdf样本筛选为例,整体效果还不错:

1
2
3
总体大小:16.17G => 563.8M
文件数量:10074 => 1105
运行时间:3 天22 小时

效果

1578993924461

基于上述方法论,笔者在近3年内,共获取国际四大厂商(Apple、Microsoft、Google、Adobe)70余次CVE漏洞致谢,其它一些厂商产品的漏洞暂且不计。

总结

本文主要介绍了协同Fuzzing的设计思路,将Fuzzing置入CI构建中的方法,并分享了决定Fuzzing效果的关键三要素:目标、策略、样本,对这些要素一一分析,并附相应的实战案例。未来,我们也会尝试多去实践和推广这种多工种协同Fuzzing的工作方式,并建设更加完善的平台管理控制系统,方便实现多人协同工作。

基于笔者水平有限,这套设计方案有些在企业内部实施的话,难免会有不足之处,欢迎业界同行斧正。

Frida框架在Fuzzing中的应用

由于Fridahttps://frida.re )动态插桩框架的跨平台、简单易用,现在已经被广泛应用于安全领域。相比Xposed而言,虽不能更底层地去Hook系统进程,但它可以免启动,应对App的hook完全够用,更关键的是,它完全可以用JavaScript来写代码,免去编译的烦恼,调试也方便。

之前在工作中,也就用Frida去Hook Android与iOS应用来做安全测试,效果挺好的,开发起来也挺高效的。本文主要围绕Fuzzing领域,来分析和记录最近一些使用Frida的Fuzzer。

定制型Fuzzer

Frida来Fuzzing APP的方法,首先推荐Project Zero大神写的Adventures in Video Conferencing系列博文,详细介绍了Hook WhatApps和iMessage的输入数据处理函数并进行Fuzzing的方法,同时也开源了Hook iMessage的工具:https://github.com/googleprojectzero/iOS-messaging-tools/tree/master/iMessage ,提供dump和发送消息的功能,自己在额外构造变异数据去Fuzzing。

这种方式特别适用于拥有私有的定制协议或数据格式的APP Fuzzing,只是需要花时间去逆向分析程序的输入数据解析流程,找到关键的处理函数。

通用型Fuzzer

最近又看到两款使用Frida的Fuzzer,出自同一人之手,用PythonJS写的,代码量不多:

  1. frida-js-afl-instr(https://github.com/andreafioraldi/frida-js-afl-instr ):打通AFL++Frida实现内存Fuzzing的工具,仅限Linux平台
  2. frida-qbdi-fuzzer(https://github.com/andreafioraldi/frida-qbdi-fuzzer ):基于FridaQBDI的Android Fuzzer,借鉴AFL的代码覆盖引导思路,实现Android平台下闭源程序的覆盖引导Fuzzing。

下面直接画时序图来看它的原理,就不贴源码分析了:

frida-js-afl-instr原理图

image-20191130121915743

frida-qbdi-fuzzer原理图

image-20191130122032208

总结

用Frida来实现闭源程序的代码覆盖引导,代码量很少,以Python和JS就可以快速开发起来,但涉及到python等进程的启动,肯定没有纯C/C++的代码运行速度快,但对于Fuzzing,一般还是够用的,还是值得学习和使用的。

Android应用逻辑漏洞半自动化挖掘思路

大清早起来就看到F-Secure LABS团队(以前叫MWR,就是那支用13个逻辑漏洞攻击chrome的团队,是pwn2own专业户)发了一篇文章“Automating Pwn2Own with Jandroid” (https://labs.f-secure.com/blog/automating-pwn2own-with-jandroid/ ),讲述如何利用Jandroid实现Android应用逻辑漏洞的半自动化挖掘思路。

专注逻辑漏洞有一些好处,尤其是打比赛用途的,撞洞率较低,且利用稳定,一般都不用搞什么内存布局控制的,MWR尤其擅长此类漏洞的挖掘,之前就在pwn2own上攻击破过华为手机和chrome浏览器。

文中介绍了Jandroid (https://github.com/FSecureLABS/Jandroid )这款开源工具,要求python 3.4以上版本运行,支持apk/dex/system.img/ext4文件解析。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
python3 src/jandroid.py -h                                            

----------------------------
JANDROID
----------------------------

usage: jandroid.py [-h] [-f FOLDER] [-p [{android}]] [-e [{device,ext4,img}]]
[-g [{neo4j,visjs,both}]]

A tool for performing pattern matching against applications.

optional arguments:
-h, --help show this help message and exit
-f FOLDER, --folder FOLDER
app分析目录,所以支持应用的批量分析
-p [{android}], --platform [{android}]
支持的平台,目前仅支持android平台
-e [{device,ext4,img}], --extract [{device,ext4,img}]
支持从连接设备、ext4、system.img中提取应用
-g [{neo4j,visjs,both}], --graph [{neo4j,visjs,both}]
支持检测结果的图表显示

它通过定义json模板来标记污点传播路径,比如拥有android.intent.category.BROWSABLE浏览器打开权限的Activity,再查找Landroid/webkit/WebView;->addJavascriptInterface看是否存在JavaScript接口,以判断是否可能存在远程攻击的条件,但这种只能是半自动化辅助,还需要人工逆向确认。

模板示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
{
"METADATA": {
"NAME": "JSbridgeBrowsable"
},
"MANIFESTPARAMS": {
"BASEPATH": "manifest->application->activity OR manifest->application->activity-alias",
"SEARCHPATH": {
"intent-filter": {
"action": {
"LOOKFOR": {
"TAGVALUEMATCH": "<NAMESPACE>:name=android.intent.action.VIEW"
}
},
"category": {
"LOOKFOR": {
"TAGVALUEMATCH": "<NAMESPACE>:name=android.intent.category.BROWSABLE"
}
},
"data": {
"RETURN": ["<NAMESPACE>:host AS @host", "<NAMESPACE>:scheme AS @scheme"]
}
}
},
"RETURN": ["<smali>:<NAMESPACE>:name AS @activity_name"]
},
"CODEPARAMS": {
"SEARCH": {
"SEARCHFORCALLTOMETHOD": {
"METHOD": "Landroid/webkit/WebView;->addJavascriptInterface",
"RETURN": "<class> AS @web_view"
}
},
"TRACE": {
"TRACEFROM": "<method>:@web_view[]->loadUrl(Ljava/lang/String;)V",
"TRACETO": "<class>:@activity_name",
"TRACELENGTHMAX": 10,
"RETURN": "<tracepath> AS @tracepath_browsablejsbridge"
}
},
"GRAPH": "@tracepath_browsablejsbridge WITH <method>:<desc>:<class> AS attribute=nodename"
}

各字段含义看示例就好了,这里不作详解。读者也可参考F-Secure发的文章,里面有详解。

总结起来,模板支持:

  1. AndroidManifest.xml的匹配搜索
  2. smali代码的匹配搜索
  3. 传播路径的图表显示,以及显示的文件格式定义
  4. 函数调用参数追踪
  5. 函数调用的起点与终点定义、追踪以及追踪深度

我直接找个apk分析运行,会出错提示以下错误:

1
2
3
4
5
6
7
8
9
10
Traceback (most recent call last):
File "src/jandroid.py", line 408, in <module>
inst_jandroid.fn_main()
File "src/jandroid.py", line 227, in fn_main
self.pull_source
File "/Volumes/Macintosh/Users/riusksk/Android-Security/工具/Jandroid/src/plugins/android/main.py", line 51, in fn_start_plugin_analysis
app_pull_src
File "/Volumes/Macintosh/Users/riusksk/Android-Security/工具/Jandroid/src/plugins/android/requirements_checker.py", line 53, in fn_perform_initial_checks
raise JandroidException(
NameError: name 'JandroidException' is not defined

直接在Jandroid/src/plugins/android/requirements_checker.py开头加以下代码即可解决:

1
from common import JandroidException

运行效果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
python3 src/jandroid.py -f ./apps -g visjs

----------------------------
JANDROID
----------------------------

INFO Creating template object.
INFO 1 potential template(s) found.
DEBUG Parsing /Volumes/Macintosh/Users/riusksk/Android-Security/工具/Jandroid/templates/android/sample_basic_browsable_jsbridge.template
INFO Initiating Android analysis.
INFO Performing basic checks. Please wait.
INFO Basic checks complete.
INFO Beginning analysis...
DEBUG 1 app(s) to analyse, using 2 thread(s).
DEBUG Created worker process 0
DEBUG Created worker process 1
DEBUG AnalyzeAPK
DEBUG Analysing without session
INFO Analysing ctrip.android.view_8.13.0_1248.apk in worker thread 0.
DEBUG AXML contains a RESOURCE MAP
DEBUG Start of Namespace mapping: prefix 47: 'android' --> uri 48: 'http://schemas.android.com/apk/res/android'
DEBUG START_TAG: manifest (line=2)
DEBUG found an attribute: {http://schemas.android.com/apk/res/android}versionCode='b'1248''
DEBUG found an attribute: {http://schemas.android.com/apk/res/android}versionName='b'8.13.0''
DEBUG found an attribute:
......
DEBUG Settings basic blocks childs
DEBUG Creating exceptions
DEBUG Parsing instructions
DEBUG Parsing exceptions
DEBUG Creating basic blocks in Landroid/support/constraint/solver/LinearSystem;->createRowDimensionPercent(Landroid/support/constraint/solver/LinearSystem; Landroid/support/constraint/solver/SolverVariable; Landroid/support/constraint/solver/SolverVariable; Landroid/support/constraint/solver/SolverVariable; F Z)Landroid/support/constraint/solver/ArrayRow; [access_flags=public static] @ 0x199210
......
DEBUG Looking for subclasses of Lctrip/business/map/SimpleOverseaMapActivity;
DEBUG ctrip.android.view_8.13.0_1248.apk took 349 seconds to analyse.
DEBUG Finished analysing ctrip.android.view_8.13.0_1248.apk with output {'bug_obj': {'JSbridgeBrowsable': False}, 'graph_list': []}.
INFO Finished analysing apps.
INFO Creating custom graph.
INFO Custom graph can be found at /Volumes/Macintosh/Users/riusksk/Android-Security/工具/Jandroid/output/graph/jandroid.html
INFO All done.

输出结果会在上面jandroid.html中显示,但由于我这里没有检测到满足JSbridgeBrowsable条件的代码,因此html里面的图是空的。如果有满足条件的代码,会得到类似如下的图:

visjs3

Jandroid还提供有GUI操作界面,包括模板创建功能,所以使用也很方便,运行以下命令即可打开:

1
python3 gui/jandroid_gui.py

image-20191102103606311

比如追踪DexClassLoader.loadClass加载外部dex文件的情况:

image-20191102104919972

再举个实例,下图是MWR当初分析三星时,一个Unzip目录穿越漏洞的函数传播路径图,漏洞被用于Mobile Pwn2Own 2017:

image-20191102104533888

所以,Jandroid还是非常适合用来挖掘逻辑漏洞的辅助工具,核心思想依然是污点追踪的思路,操作简单,可视化效果也很好。基于模板的定制化,增加了其运用的灵活性,尤其对于复杂的业务逻辑设计,很适合作定制化地批量检测,但依然需要人工分析确认,并非完全自动化的。

漫谈网络安全应急要略

【注】:本文仅代表个人观点,与公司立场无关。

早上看到朋友圈有人说Metasploit公布BlueKeep远程执行漏洞的利用,一些安全群里也有人喊着加班了,但这漏洞明明很早就已经发布补丁了,现在才加班应急明显是有问题的。因此才有了本文,谈谈关于安全应急的一些个人想法。

要略一:急则治其标,缓则治其本

Sep-07-2019 12-20-44

在韩剧《幽灵》中,男主角在入侵犯罪者的电脑后,发现他正在上传受害者视频,在电脑里他看到一份名为申孝静的文件,里面全是照片,男主在照片里看到那个戴金表的男人,还没看清扫描出他的脸,幽灵就把网线拔掉了。

假如服务器因漏洞被入侵,是先修漏洞还是先上面韩剧那样拔网线呢?

估计你想拔网线都拔不到,可以先关闭外网止损。虽然这里本因是漏洞导致的,如果入侵后还在线上补漏洞,估计等你补完,裤子都被脱光了。

这里”标”是数据泄露,”本”是漏洞,紧急情况下,先治标,及时止损,防止数据泄露;缓解之后,再治本,修补漏洞,也包括安全系统监控与拦截机制被绕过的问题。

如果今天还在应急BlueKeep漏洞,说明补丁日的时候没有及时打补丁,才导致今天的局面。

毕竟,你总不能老是靠拔网线来解决问题吧!

要略二:数据安全高于一切

Sep-07-2019 12-16-48

日剧《医龙》中,跟随男主的一位护士突发气胸,情况危急,如果叫救护车可能来不及,于是男主直接拿根笔管折断,插入患者的两侧胸腔放气,以降低胸腔压力。正常人的胸腔是负压,当气体进入后会压缩肺脏,导致呼吸困难,片中的场景应该是张力性气胸,即胸腔压力大于外部气压时,才插入胸腔放气。但是,如此风骚的非常规手段,未消毒,还产生新创伤的治疗手段,明显是不符合医疗操作流程的,但若不这样做,又可能没命。所以,危急情况下,总有一点最高优先级的标准,那就是:生命高于一切!

Sep-07-2019 12-17-55

在各公司里面,都有自己要求的产品发布流程,从需求、开发、测试、发布都有一系列的流程要走,这也是对产品质量的保证。但是,若被外部发现严重漏洞,想发布补丁也这样走一遍,中间还涉及各种审批,搞完都得好多天了,到时候,裤子又要被脱光了!那到底是遵守,还是不遵守。

这就要求同样要有一条最高优先级的标准,那就是:数据安全高于一切!

数据包括公司保密信息、用户数据等等不宜公开的数据,如果在危害数据安全的情况下,就不该过于拘泥于繁文缛节,应有相应的应急通道去完成快速发布安全补丁的途径。

要略三:举一反三,触类旁通

timg

每起安全应急事件背后,都有其导致事件的问题存在,很多时候它又代表着一类问题,而非单一案例作单一处理,最好能保证一个案例,引出一类问题并解决掉。

比如由于SQL注入导致的拖库事件,并非止损修漏洞就完事了,其背后的扫描器为何漏扫,WAF为何被绕过,或者漏洞代码为何回滚(上个月苹果就因此导致iOS 12.4被拿旧洞越狱)。解决背后引发漏洞的各类问题,是不是就能够拿扫描器发现更多业务的同类漏洞,WAF是不是能够帮各多业务防御漏洞,代码发布流程的完善是否可以避免代码回滚导致的漏洞……

要略四:广开言路,以德服人

Sep-07-2019 17-33-27

在电影《巴斯特·斯克鲁格斯的歌谣》中,巴斯特·斯克鲁格斯是个牛仔,穿戴着闪闪发光的马刺和崭新的白色马裤,喜欢唱歌,还有无人能敌的好枪法,他自诩是全西部决斗掏枪最快的枪手,还把这编成了歌谣,天天弹着吉他唱在口头,他以一种无敌的姿态一路杀一路唱一路跳。

Sep-07-2019 17-32-53

但最终他遇上了旗鼓相当的对手,被人以自己惯用规则和套路一枪爆头。

这个故事告诉我们,装逼一时爽,过头火葬场。

同样地,再牛逼的安全系统也可能被绕过,再安全的网站也可能被入侵,没有绝对安全的地方。

现在流行建设SRC与众测,也是为了与自身安全团队的能力作互补,广开言路,博采众长,改善自身安全系统,解决自己未能发现的问题。

为何提到以德服人,一方面是指善待白帽子,保持有效沟通,另一方面是指避免”文人相轻”的现象。谁都年轻过,搞技术的人有时多少有点傲气,报洞的BS收洞的,甚至报洞者之间互相BS。如果企业也带着相同的情绪,难免会导致与白帽子之间沟通矛盾,所以说善待白帽子,以德服人,哪怕白帽子少凌晨两三点搞事,也是好的。

这些年,微软对漏洞的处理的态度变化最大,从最初放言绝不为漏洞买卖,散漫地漏洞处理态度,到现在及时响应,建立完善的漏洞奖励计划,奖金力度也在不断提高,同时每年在BlackHat上公布TOP 100最具价值的安全研究员名单,赋予帽子荣誉感。

这些都代表着行业对漏洞,对白帽子的态度的一路转变历程。

要略五:未雨绸缪,防范未然

timg2

现在行业都在推广DevSecOps,是由Gartner 在2012年的一份报告中提出的概念。在这份报告中,Gartner提出信息安全专业人士需要更主动的融入DevOps的实践中,秉承DevOps的精神,拥抱团队协作、敏捷和职责共担的哲学。说得直白点就是,将安全融入到研发、运营等各个流程中,以实现安全自动化,连续响应和检测机制,帮助各团队之间协同合作。

在应急事件中至少覆盖到:

  1. 事前防范:包括漏洞扫描、代码审计、渗透测试、威胁情报、数据保护等等;
  2. 事中拦截:包括WAF、EDR、RAPS、IDS、杀软等等;
  3. 事后追溯:包括日志记录、取证系统等等。

要略六:犯罪者,虽远必诛

QQ20190907-194700

早作最坏的打算,因为白帽子也有”黑化”的可能。之前微软得罪过多少个白帽子了,就曾有白帽子在一气之下,每隔一段时间就爆0day出来。虽然其中微软也有责任,但白帽子这种行为总是不对的。

特别鄙视那些借测试之名,行不轨不事的人,搞了破坏还要钱,这就是不厚道,耗人品的耻事。

即使是现在的SRC与众测,虽说是奖励机制,但本质上依然是种利益交换行为,有利益就可能产生冲突。所以,需要时刻为这种冲突准备着。

坚持”不搞事,不怕事”的态度,贯彻”决不放弃使用武力”的作战方针,保留犯罪证据,在必要的时候,坚决拿起法律武器捍卫自身权益。

一句话:犯罪者,虽远必诛!

vulwar

安全研究的价值思考

【注】:纯属个人言论,与公司立场无关!

最近的Black Hat大会议题ppt已提供下载,里面有两个非技术议题,其视角比较有趣,一些问题值得思考,因此才有本文。

这两个议题分别是”Project Zero File Years Of Make 0day Hard”和”Selling 0-days to governments and offensive security companies”,一个讲述5年来Google的Project Zero团队在漏洞研究上的工作效果,一个讲述关于漏洞交易的一些现状、流程。

安全研究都干啥

安全研究并不局限于漏洞领域,但它依然是目前最主流的方向,研究范围也可以包括网络安全、反病毒、大数据安全、业务安全等诸多安全领域。这里主要聊下漏洞领域的研究,看看Project Zero的人主要都在干啥:

image-20190818142847773

总结一下就是(主要指漏洞研究领域,估计很多人只干1、3、4的工作):

  1. 漏洞挖掘与利用
  2. 方法论建设
  3. 技术写作
  4. 行业交流与合作
  5. 软件工程化建设,可能是指DevSecOps,包括安全防御策略建设、libfuzzer自动化测试等的应用

###从招聘职责看研究目的

谈研究价值,不妨先来谈谈研究的目的,我特意从各招聘网站上搜集了一些关于安全研究岗位的招聘信息,主要统计其岗位职责描述的关键词,生成如下词云:

职责

可以看到,当前的研究岗位普遍就是招漏洞挖掘职位的,都是搞主流系统及软件为主,但挖洞的目的又是为什么呢,这种在很少企业会写在招聘帖的。从统计结果看,主要有以下3个研究目的:

  1. 挖掘主流系统/软件漏洞;

  2. 帮助安全产品提升检测能力;

  3. 为业务提供技术支持。

第一点是手段,等于啥也没说,第2点算是做安全产品,第3点是得看是什么业务,如第2点也算业务,但如果是一些非安全产品业务,其实所能提供的技术支持就相对比较局限,可能人家业务也不一定看得上你这研究。

影响力价值

搞安全研究,普遍都是为了影响力公关(PR),国内外均是如此,BlackHat上的Pwnie Awards都有一个“最名不副实漏洞奖”,叫做”most over-hyped bug”,就是用来批评那些过度炒作的漏洞。但是一些确实危害比较大的漏洞,及时负责任地披露反而有利于防御工作的开展。Project Zero议题中讲到一句话,开放的攻击研究相对攻击者而言,对防御者更为有利。之前国内试颁行的某提案,因可能阻碍安全研究者公开研究成果,遭到不少圈内人的反对。这跟古时候,有的国家禁止人民用刀一样,最终只是阻碍生产力的发展而已。其实只要不是急功近利,获得与研究成果相匹配的影响力也是合理的。那获得影响力之后的价值呢?对团队,对个人,可能获取得更多交流与学习的机会,也可能获得更多业务合作机会,直接点,可能找份工作防止中年危机都更有资本了。

商业价值

何为商业价值?就是赚钱嘛!通过安全研究落地为产品,然后拿去卖;也可提供技术服务,比如帮助对IoT、车联网产品等新兴行业产品进行安全测试。产品一般比技术服务更值钱,技术服务经常是一波过,产品却是可以长期收费的,比如IDA一年卖几万刀,用户每年都得交钱,而若只是提供逆向服务,费劲且不持久,赚得还少。如果是漏洞交易,高质量的漏洞利用链也是可以获得不菲的利益。在0day漏洞交易感兴趣的,主要涉及以下3类角色:

image-20190818144822263

  1. 防御型企业、漏洞奖励计划和平台
  2. 黑客比赛举办者,类似漏洞收购中间商,自己可能也会去挖洞,也可能收购poc来自己写exploit,或者直接收购exploit,再转手卖出去赚差价
  3. 攻击型企业、政府、黑产团伙

现在国内已经限制参加Pwn2Own之类的国外比赛,从2018年开始,国内由”天府杯”比赛代替,主要是防止漏洞外流危害国家网络安全。这些比赛也推动了厂商对漏洞处理的态度,以及漏洞奖励计划的建设,使得报告者能够合法地获得相应的奖励和认可。

新型业务安全预防

提前研究一些公司业务可能涉足的新领域,避免新兴业务产品出来后,无能力解决上面的安全问题。但整个的前提是,该新产品能活下来,否则一切都是白搭。

行业贡献

在安全行业贡献榜上,Project Zero无疑是佼佼者。在5年内,他们共贡献1500+个主流系统/软件漏洞,推动很多安全防御机制的诞生,甚至影响漏洞在市场上的价格。漏洞研究者有时担心手上的漏洞被撞掉,会直接报给厂商,混个致谢,搞不好年底还能混个”MSRC Top 100”,今年开始它改名叫”最具价值安全研究员”,更高大上了。这个月,我就被Project Zero的人撞掉了一个微软漏洞。在PZ分享的议题里面,提出一些衡量”make 0day hard”的标准,但毕竟是相对概念,仅当作参考:

  1. 挖到品相优秀的漏洞所花费的时间;

  2. 漏洞平均生存时间;

  3. 撞洞数量;

  4. 漏洞利用链的长度;

  5. 新型高质量的攻击面的发现概率。

个人保值防老

研究本身就是一种学习方式。相信爱学习的人,最终运气都不会太差。尤其是现在鼓吹35岁中年危机的互联网时代,保持学习是最靠谱的个人保值防老方式。如果保持工作内容不变,那么通常头一年所积累的技术与工作方法足够应付绝大部分工作。若再不搞点有挑战的新工作内容,或者业余做点研究,那就要成为拿着一套技术吃N年的”老白兔”了。持续学习,保持或者超越与年龄相符的技术能力才是王道。

一些值得学习的Fuzzer开源项目

之前GitHub上有人整理过一个叫Awesome-Fuzzing的资料,整理了关于Fuzzing技术的电子书、视频、工具、教程以及用于练习的漏洞程序。整体上不错,但工具上还是不够全,有些不错且希望阅读代码学习的工具,发现未在其中,因此重新整理出下面这一份资源,其中有些还曾二次开发过,有些是还未来得及学习的,写出来权且当作学习计划。

  1. AFL——支持源码插桩的代码覆盖引导的Fuzzer,绝对是fuzzer领域的一大里程碑,虽然它也支持基于QEMU的闭源程序,但效果不好,且容易出错,由它衍生出来非常多afl分支版本,借助它已经被挖出非常多的漏洞,但它的变异策略其实有待提高。

    http://lcamtuf.coredump.cx/afl/

  2. WinAFL——windows版本的afl,使用DynamoRIO去插桩闭源程序以获取代码覆盖率信息,同时支持硬件PT获取覆盖率信息,但PT获取覆盖率其实并没有插桩获取得全,但速度可能会快一些。

    https://github.com/googleprojectzero/winafl

  3. AFLFast——加速版的AFL,Fuzzing速度确实会比原版快一些。

    https://github.com/mboehme/aflfast

  4. Vuzzer——支持闭源程序的覆盖引导Fuzzer,使用LibDFT的pin工具实现数据流追踪,结合动静态分析,以获取更多的代码路径,比如比较语句中的比较值,它会先作记录,再未来变异时使用。

    https://github.com/vusec/vuzzer

  5. PTfuzzer——Linux平台下的采用 Interl PT硬件支持的覆盖引导Fuzzer,所以它支持闭源程序。

    https://github.com/hunter-ht-2018/ptfuzzer

  6. afl-unicorn——采用Unicorn模拟指令的AFL,支持Linux闭源程序

    https://github.com/tigerpuma/Afl_unicorn

  7. pe-afl——通过静态插桩实现针对Windows闭源程序的覆盖引导的AFL Fuzzer,支持用户层应用和内核驱动

    https://github.com/wmliang/pe-afl

  8. kAFL——支持QEMU虚拟机下的系统内核Fuzzing的AFL,适用于Linux、macOS与Windows

    https://github.com/RUB-SysSec/kAFL/

  9. TriforceAFL——基于QEMU全系统模拟的AFL,借助系统仿真器实现分支信息跟踪,支持Linux内核Fuzzing

    https://github.com/nccgroup/TriforceAFL

  10. ClusterFuzzer——Google开源的可扩展的Fuzzing基础设施

    https://github.com/google/clusterfuzz

  11. LibFuzzer——进程内覆盖率引导的开源的fuzz引擎库,属于llvm的一部分,在各大主流开源库中,以及Google内部最经常用的安全测试工具

    https://llvm.org/docs/LibFuzzer.html

  12. OSS-Fuzz——基于LibFuzzer的开源软件Fuzzer集合,实现docker下自动下载、编译安装及运行

    https://github.com/google/oss-fuzz

  13. honggfuzz——Google开发的基于软硬件的覆盖驱动型Fuzzer,单纯暴力Fuzz的效果也挺好的,支持多平台,包括Linux\macOS\Windows\Android

    https://github.com/google/honggfuzz

  14. KernelFuzzer——跨平台内核Fuzzer框架,不开源策略,只在其paper中提及变异策略,需要自己实现,支持Windows、OSX和QNX系统,但只提供Windows编译脚本

    https://github.com/mwrlabs/KernelFuzzer

  15. OSXFuzzer——基于Kernel Fuzzer的macOS内核Fuzzer

    https://github.com/mwrlabs/OSXFuzz.git

  16. PassiveFuzzFrameworkOSX——通过Hook实现被动式的OSX内核Fuzzer

    https://github.com/SilverMoonSecurity/PassiveFuzzFrameworkOSX

  17. Bochspwn——基于Boch插桩API实现Double Fetches内核漏洞的检测

    https://github.com/googleprojectzero/bochspwn

  18. Bochspwn-reloaded——基于Boch插桩API实现内核信息泄露的检测

    https://github.com/googleprojectzero/bochspwn-reloaded

  19. syzkaller——基于覆盖率引导的Linux内核Fuzzer,需要基于其模板语法实现API调用模板,提供给syzkaller进行数据变异,也曾被移植到其它平台

    https://github.com/google/syzkaller

  20. dharma——基于语法模板生成的Fuzzer,由Mozilla开源的用于Fuzz Firefox JS引擎

    https://github.com/MozillaSecurity/dharma

  21. domator——Project Zero团队开源的DOM Fuzzer,用python实现基于模板生成的Fuzzer

    https://github.com/googleprojectzero/domato

  22. Fuzzilli——基于语法变异的JavaScript引擎Fuzzer,先通过语法模板生成测试用例,再生成中间语法进行变异,结合覆盖率引导以触发更多代码路径

    https://github.com/googleprojectzero/fuzzilli

  23. Razzer——内核竞争条件漏洞Fuzzer

    https://github.com/compsec-snu/razzer

  24. ViridianFuzzer——用于Fuzzing Hyper-V hypercalls的内核驱动,由MWRLabs公司出品

    https://github.com/mwrlabs/ViridianFuzzer

  25. ChromeFuzzer——基于grinder语法生成器改装的Chrome浏览器Fuzzer

    https://github.com/demi6od/ChromeFuzzer

  26. funfuzz——Mozilla开源的JS fuzzer工具集合,主要用于Fuzz SpiderMonkey

    https://github.com/MozillaSecurity/funfuzz