在蜘蛛侠Peter Parker的生日这一天,我们为大家带来一篇清华大学软件与系统安全课题组(VUL337)投稿的USENIX Security 2022研究论文——StateFuzz: System Call-Based State-Aware Linux Driver Fuzzing
1. Background
软件漏洞是网络空间最重要的安全威胁之一,安全人员需要及时的挖掘和修复软件中的漏洞来防御黑客攻击。以AFL[1]为代表的代码覆盖率引导的模糊测试(Code coverage guided fuzzing)已经成为了自动化漏洞挖掘最有效的方法之一。
首先介绍一下代码覆盖率引导的模糊测试的基本流程。如下图1所示
图1. 代码覆盖率引导的模糊测试工作流程
代码覆盖率引导的模糊测试基于遗传算法,首先fuzzer从种子池(seed corpus)选择一个种子(seed)并变异,产生新的测试用例。之后fuzzer将这些新的测试用例(testcase)作为输入执行经过了插桩的被测程序,观察被测程序是否有异常行为或者崩溃(crash),并根据插桩产生的反馈(feedback)保留触发了新代码的测试用例作为新种子。
2. Motivation
然而,代码覆盖率引导的模糊测试在测试具备复杂状态的程序(比如网络协议程序、内核驱动)时存在局限,即fuzzer缺乏指导来遍历程序状态。原因在于代码覆盖率引导的模糊测试只关心代码覆盖率,因此会丢弃没有触发新代码的测试用例,即使这些测试用例触发了新的状态。以IJON[2]论文提出的迷宫程序为例,在图2的代码中,代码覆盖率引导的模糊测试可以轻松的覆盖所有代码行,在此之后,即使x和y有不同取值,也会被模糊测试器丢弃,因为没有触发新的代码行。这样一来,因为缺乏指导,模糊测试很难通过随机生成x和y,来遍历所有的x、y取值组合来触发Bug()函数。
因此,作者认为对这些程序,需要使用状态敏感的模糊测试(state-aware fuzzing)。
图2. 迷宫示例代码
3. Design
至于如何进行状态敏感的模糊测试,作者归纳了3个要回答的问题:
Ø (1) 什么是程序状态?
Ø (2) 如何识别程序状态,并在模糊测试的时候跟踪程序状态?
Ø (3) 如何用程序状态信息指导模糊测试?
对于第一个问题“什么是程序状态”,程序状态理论上是程序执行的上下文信息,包括所有内存和寄存器的取值。然而,这些信息太过庞大,在实际fuzzing的时候跟踪监控所有这些信息是不可行的。因此,作者认为考虑到可行性,fuzzer只需要关心程序状态的一个子集。
最近的研究工作提出了一些表示部分程序状态的方法:IJON[2]提出人工在程序代码中添加标注,将标注过的数据作为程序状态,然而这种人工标注需要专家知识和大量人力;AFLNet[3]提出使用程序状态码表示程序状态,但是很多程序不会用到状态码。
经过对一些开源程序的调研,作者发现在程序中用变量表示程序状态十分常见。综上,作者认为fuzzing时关心的程序状态为用变量表示的程序状态,作者将表示了状态的变量称为状态变量(state-variable)。
于是,第二个问题“如何识别程序状态”就等价于如何识别程序中的状态变量。作者总结了状态变量的三个特征:需要有很长的生命周期,可以跨越不同的程序状态来记录状态信息;变量会被用户更新(update)来产生状态转移;状态往往可以影响程序行为,因此状态变量需要能影响程序的控制流或者内存访问。同时,作者观察到状态丰富的程序往往会使用多次交互的输入,每次交互会触发相应的程序行为(program action),例如FTP server程序会接收User、Pass等不同的packets,User packet会触发USER请求对应的请求处理函数,Linux内核里的file_operations也会根据不同的系统调用执行对应的operations。在这些程序中,状态变量经常被不同的program action共享来实现状态转移或者状态查询。因此,作者提出通过静态分析识别这些program action之间共享的变量来作为状态变量(识别过程如图3所示),并且在fuzzing的时候监控这些变量。
图3. 提取状态变量
对于第三个问题“如何使用程序状态指导fuzzing”,一个直观的想法是仍然借助遗传算法,使用state coverage作为fuzzing的feedback。然而,如果我们把每一个状态的取值作为一个新的状态,就会出现状态爆炸的问题,因为一个32位的变量就有2的32次方个取值。为此,作者提出可以通过符号执行提取程序约束信息,将一些状态相似的取值合并到一起,将变量的值域分割为多个值域范围,不同的值域作为不同的状态,同时变量的极值也可以反映程序的状态。最后,作者提出了一个三维的feedback机制和一个三层种子池,将代码覆盖率、状态变量值域范围覆盖率和极值率作为fuzzing feedback指导fuzzer。
作者实现了一个StateFuzz原型,用于测试Linux驱动,架构设计如图4所示。
图4. StateFuzz架构
4. Evaluation
在实验评估阶段,作者首先评估了StateFuzz提取出来的状态模型。StateFuzz分别从Linux 4.19内核驱动和MSM 4.14内核驱动中提取出了6055个和5037个状态变量,平均每个状态变量划分了3个值域范围。经过人工验证,StateFuzz可以成功识别出90%的状态变量。
之后,作者对StateFuzz的代码覆盖率和状态覆盖率进行了评估,在测试Linux 4.19内核驱动实验中,StateFuzz的代码覆盖率比Syzkaller高19%,值域范围覆盖率比Syzkaller高32%,更多的细节请参见论文。
最后,作者评估了StateFuzz的漏洞发现能力。StateFuzz在Linux 4.19内核驱动以及MSM 4.14内核驱动中一共发现了20个漏洞,其中19个被确认,有14个被确认的漏洞被分配了CVE。另外,在19个被确认的漏洞中,有9个漏洞获得了来自谷歌或高通的漏洞赏金奖励。
图5. StateFuzz发现的漏洞
5. 结论
在上文的描述中,我们展示了StateFuzz,一个状态敏感的模糊测试方案。StateFuzz通过静态分析识别状态变量表示状态,并通过跟踪状态变量的值域范围覆盖率和极值指导fuzzing。理论上,StateFuzz可以扩展到网络协议程序(作者已经进行了初步的探索,可以参见论文NSFuzz[4])、智能合约等状态丰富的程序。
论文PDF:https://github.com/vul337/StateFuzz/raw/main/statefuzz.pdf
Reference:
[1]. Michal Zalewski. 2014. American Fuzzy Lop. http://lcamtuf.coredump.cx/afl/
[2]. Aschermann C, Schumilo S, Abbasi A, et al. Ijon: Exploring deep state spaces via fuzzing[C]//2020 IEEE Symposium on Security and Privacy (SP). IEEE, 2020: 1597-1612.
[3]. Pham V T, Böhme M, Roychoudhury A. AFLNet: a greybox fuzzer for network protocols[C]//2020 IEEE 13th International Conference on Software Testing, Validation and Verification (ICST). IEEE, 2020: 460-465.
[4]. Qin S, Hu F, Zhao B, et al. Registered Report: NSFuzz: Towards Efficient and State-Aware Network Service Fuzzing[J].
作者介绍:赵博栋,清华大学网络科学与网络空间研究院博士生,导师是张超老师。他的主要研究方向为程序分析、Linux内核模糊测试和容器模糊测试。
课题组介绍:清华大学软件与系统安全课题组(VUL337)由张超老师带领,团队主要研究兴趣为:针对软件与系统安全领域漏洞与恶意代码等问题,面向主机、移动设备、区块链、物联网、车联网、人工智能系统等目标,研究自动化、智能化攻防技术,构建智能分析系统;针对数据安全与隐私计算问题,研究芯片、系统、算法协同的实用化解决方案。团队长期招聘对安全感兴趣的博士后、工程师、客座研究生、实习生等。
张超老师主页:https://netsec.ccert.edu.cn/chs/people/chaoz/
推荐站内搜索:最好用的开发软件、免费开源系统、渗透测试工具云盘下载、最新渗透测试资料、最新黑客工具下载……
还没有评论,来说两句吧...