“今天来介绍ISSTA 21' [1] 和 ICSE 24' [2] 上面两篇有关利用Fuzzing降低静态分析工具误报的文章。整体思路都是依据static analysis从代码中抽取片段(minimized slice),随后通过harness来进行fuzzing分析,判断漏洞是否可触发。”
1. 背景介绍
静态分析工具在软件开发流程中非常常用,能够在不运行代码的条件下发现软件中的漏洞。然而静态分析工具往往存在整体误报率过高导致使用困难的问题,之前公众号团队做过一些统计,产生误报的原因很复杂,其中主要的原因有例如:
-
算力局限,在动态数值处易产生误报
-
对于Loop循环次数处理设计缺陷
-
无法识别数据过滤函数
1.1 Motivation Example走起
下面给出一个motivation example
当运行static analysis工具(如RATS)对这段代码进行检查时,它会将第16行标记为buffer overflow。然而,这显然是一个误报,因为第16行的strcpy操作永远不会超出分配的指针ret的界限。这是因为12行分配给指针p的大小总是等于所有输入字符串的长度+1。
2. Overview & Implementation
学术界为了解决这样的问题,提出了很多方法,包括改进静态分析,函数摘要等等方法。今天介绍的两篇文章是通过对于可能包含漏洞的candidate fuction进行动态fuzzing,来判断是否存在误报。
ISSTA 21‘[1] 开发的工具为Helium,ICSE 24’ [2]开发的工具为FuzzSlice[3]
workflow
这种类型的工作的challenge主要有以下几点:
CH1:静态分析工具只会报出存在漏洞的代码片段,如何构造可编译、可运行的文件?
CH2:程序中有很多与漏洞无关的代码,如何构建最小的code slice?
CH3:动态测试如何保证覆盖率和准确性?
2.1 Minimal Slice Creation
这一步,两个工具都使用了递归囊括依赖的方式,例如下图,是静态分析工具的一个warning,表示ftpBuildTitleUrl函数存在漏洞。然而这个代码片段语义上不全,1023行的if缺少右括号;依赖上也不全,例如1004行的len没有被定义就被使用。
如何从这个代码片段生成“minimized slice”是本节要解决的问题。
针对这种问题,Helium和FuzzSlice提出了不同的解决方法。
2.1.1 FuzzSlice
FuzzSlice 在语义上的解决方法比较粗暴,直接提取整个ftpBuildTitleUrl函数,随后递归地囊括所有依赖,例如发现strcmp需要被包含,就在minimized slice中包含对应的头文件以及环境依赖。
FuzzSlice会多次对minimized slice进行编译,根据每一次编译的log,从源代码中递归地寻找对应的依赖。
例如下图的warning意味着需要加入“OPENSSL_malloc”的依赖,FuzzSlice就会抽取并查询包含源文件语义的XML,找到OPENSSL_malloc的定义处并包含进来。
这里用到的工具有:Bear[4] , srcML[5]。Bear能够记录编译时使用的命令行。srcML能够将源代码全部抽取为XML结构,方便使用XPath查询,定位target program依赖所在的位置。
2.1.2 Helium
Helium 在语义上多了一步LCA-Based Synatactic Patching,也就是并不是直接抽取整个ftpBuildTitleUrl函数,而是只抽取这个函数中和漏洞相关的语句并补充。最终的结果如下图:
可以看到,Helium仅补充了缺失的len和t两个变量,以及缺失的括号。整体算法十分复杂,详细算法可查询论文内容。
函数补充完成后,Helium也使用Bear进行可编译文件的构建。
2.2 Fuzzing
2.2.1 Harness
两个工具为了Fuzzing的运行,都会为target program添加一个main函数,作为代码片段的Harness。识别input变量的方法是:如果在代码片段中使用变量𝑣之前没有找到变量𝑣的定义,那么变量𝑣就是一个input变量,应该添加进main函数。
2.2.2 Input
FuzzSlice 使用 libfuzzer 进行fuzz,过程中只改变 “C primitive types” 的值。Helium 则使用了KLEE, Fuzzers and Valgrind 三个工具进行fuzz,所有输入也都是随机生成。
3. Evaluation
两篇文章的作者都使用了公开的Test Suite和 Real-World Dataset进行测试。
FuzzSlice成功检测出了864/864个Juliet Test Suite的False positive,并且对于Real-World Dataset,成功编译了244/265个minimized slice,并在warning中检测出来了143/265个“可能的误报”(下图中PFP), 25/265个确认可被触发的crash(下图中C)。
Helium在Real-World Dataset中成功编译了68.5%的minimized slice,找到了205/280个“可能的误报”,48/280个确认可被触发的crash。
Helium编译成功数量表较少主要是由于Helium协助降低代码的片段大小的算法比较复杂,但是最终效果要强于FuzzSlice。
4. Discussion
这里由于两者的Target 不同,Evaluation的结果无法直接比较。总而言之,利用Fuzzing进行static analysis的FP elimination确实能达到不错的效果,并且在一定程度上能够辅助生成PoC。
但是实际情况中,这些触发漏洞的PoC不一定有用,因为Fuzz出来的输入很有可能并不会在real-world software中被产生并传入函数,毕竟两个工具的测试目标都是“code slice”以及自定义的main函数构成的程序。
[1] “FuzzSlice: Pruning False Positives in Static Analysis Warnings through Function-Level Fuzzing”: https://www.researchgate.net/publication/374114151_FuzzSlice_Pruning_False_Positives_in_Static_Analysis_Warnings_through_Function-Level_Fuzzing
[2] “Validating Static Warnings via Testing Code Fragments”:
https://sites.google.com/view/helium-2021
[3] “FuzzSliceICSE,” Sep. 2023, [Online; accessed 11. Sep. 2023]. [Online]. Available: https://github.com/NobleMathews/FuzzSliceICSE
[4] Bear: https://github.com/rizsotto/Bear
[5] srcML: https://github.com/srcML/srcML/tree/master
原文始发于微信公众号(安全研究GoSSIP):G.O.S.S.I.P 阅读推荐 2024-04-29 利用Fuzzing降低静态分析的误报
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论