看到gossip的推送,所以细细读了一下这篇文章,感觉还是挺有收获的。
如果觉得文章太长,可以看gossip公众号的推送。
https://mp.weixin.qq.com/s/X3l2stiMTxoIt77wHvQW_g
文章的数据集开源于:https://doi.org/10.5281/zenodo.6515687
简介
静态分析工具经常用来检测安全漏洞。现有的静态分析的实现很多,很难去做一个客观的比较来看哪个工具在检测漏洞上最有效。现有的方法存在两个局限。一是,他们使用合成的数据集,漏洞不能反映安全漏洞的复杂性。二是,不提供可区分的分析,比如检测出漏洞的类型都不一样。因此,关于分析器检测漏洞的能力的结论不能泛化到真实程序。
这篇文章提出了一种方法,来自动评估静态分析工具的有效性。文章评估了5个开源和1个商用的静态分析工具。具体来说,对27个软件,总共1百万行代码和192漏洞进行了评估。结果表示,静态分析工具在合成漏洞的表现上很好,在真实程序的benchmark上,静态工具的漏报会高达47%-80%。组合这些结果,可以降低15%的漏报率。许多漏洞仍然没被发现,尤其是经典的内存相关的安全漏洞。
CVE Mapping and Grouping
不同的静态分析器使用不同的识别方法来划分漏洞的类型。比如FlawFinder使用CWE来做漏洞划分。这些不同的划分使得很难自动去评估静态工具找到的漏洞。对于这个原因,文章构造了一个映射来给每个漏洞分类器分配一个CWE ID。比如下面的这个例子。UAF,DF都给分为CWE-664。更具体的mapping,论文没有给出,不过可以去细看下文章给的dataset。
Benchmarking
Benchmark Dataset - Ground Truth
现有的静态分析工作主要是用juliet test suite作为测试集。但是,这些Juliet Test Suite的漏洞和真实世界程序的还差很多。但是带有真实世界程序漏洞的数据集里,漏洞比较少,大多是同一类型,或者没有文档说明(比如没说明白漏洞的类型)
这篇文章选择的是magma数据集和两个真实程序。magma是建立在合法的CVE报告上,包含了很多中的漏洞。magma数据集使用的是一种前向导入(front-porting)的方法。就是旧版本的漏洞被重新插入到最新版本的程序中。对于每个导入的漏洞,magma都有指出漏洞的root cause和他的manifestation。root cause就是漏洞的根源,manifestation是漏洞表现的地方。
除了magma以外,还用了Binutils和FFMpeg这两个程序。因为这两个程序包含很多well-documented的漏洞。
漏洞验证 . 由于许多分析器在build过程时候进行分析,所以要确保源码在build过程时,不会因为错误的build设置而被预处理器给处理掉。如果被去掉了,就需要重新设置,或者把这个漏洞从评估中剔除。
另外,由于使用的是真实程序作为数据集,所以静态分析器有可能发现未知的漏洞。然而,评估的目的是静态分析是否能够在benchmark中找到已知的漏洞,作者认为这就足够说明静态分析器的有效性了。也就是不考虑这个未知的漏洞。
漏洞的类型和类别,文中分为五大类:
- Improper Control of a Resource Through its Lifetime(CWE664):主要是内存破坏漏洞。
- 越界读写(CWE-{119,125,787})
- UAF(CWE-415,416)
- 资源管理错误(CWE 399,770,772,401)
- 类型转换(CWE 681)
- Incorrect Calculation(CWE682):错误的计算,然后结果被用作内存分配和访问上。
- 除零错误(CWE 369)
- 整数溢出(CWE-190)
- 错误的缓冲区长度的计算(CWE-131)
- Insufficient Control-Flow Management(CWE691):表示控制流被操控那类的漏洞
- 循环没有退出条件:CWE 835
- 攻击者消耗额外的资源,或者让程序导向断言,导致DoS
- Improper Check or Handling of Exceptional Conditions(CWE703):没有处理好异常条件
- 空指针解引用(CWE 476)
- Improper Neutralization(CWE707):没有处理好程序的输入和输出。
- 畸形的字符串作为参数或者环境变量(CWE 20)
- improper validation of array indices(CWE 129)
静态器所支持的漏洞类型如下表。
- FLF:FlawFinder
- IFR:Infer
- CPC:CppCheck
- CCH:CodeChecker
- CQL:CodeQL
- CSA:不知名商业软件。
漏洞检测的粒度
由于静态分析器检测漏洞的方式五花八门,有的指出漏洞的root cause,有的指出漏洞的manifestation。这样就不好判断静态分析工具到底检测出了漏洞没有。作者提出了一种指标Fault-Error Conformity(FEC)。root cause所在的函数的与manifestation所在的函数的交集的数目除以manifestation函数的数目。也就是FEC越接近于1,漏洞的root cause和manifestation的重叠越高。
实验结果表明,大部分的漏洞的root cause和manifestation都是重叠的。
因此,作者认为可以从函数级别来作为合适的代码抽象去评估工具的有效性。
Evaluation Setup
研究问题
评估主要回答以下三个问题:
RQ1:静态分析器的有效性。
RQ2:组合分析器提升的有效性。
RQ3:最好检测和最难检测的漏洞是啥?
评价指标
检测的漏洞的比率:
Vuln.DetectionRatio=#Detectedvulns÷#Allvulns.inbenchmarkVuln. Detection Ratio = \#Detected vulns \div \# All vulns. in benchmarkVuln.DetectionRatio=#Detectedvulns÷#Allvulns.inbenchmark
标记函数的比率:
MarkedFunctionRatio=#MarkedFunctions÷#AllfunctionsinbenchmarkMarked Function Ratio = \#Marked Functions \div \#All functions in benchmarkMarkedFunctionRatio=#MarkedFunctions÷#Allfunctionsinbenchmark
什么情况下,漏洞才算被检测出来?
- 至少一个被漏洞影响的函数被找出来,而不管漏洞类型分得对不对。(S1-1)
- 至少一个被漏洞影响的函数被找出来,同时漏洞类型也要正确。(S1-2)
- 所有被漏洞影响的函数都被找出来,不管漏洞类型对不对。(S2-1)
- 所有被漏洞影响的函数都被找出来,同时漏洞类型也正确。(S2-2)
静态分析器和测试程序的配置
对于静态分析器,把benchmark里的漏洞类型的checker打开了。如果checker不是找安全漏洞的,就关掉。对于CodeQL,我们使用Semmle提供的外部库和查询。
修改SQLite3的编译过程,使得所有的C文件都会被单独地编译,而不是合并到一个代码文件中。这主要是因为有的分析器会在build的过程中分析程序。Binutils中漏洞在19个程序中都有,也是分别编译。
Evaluation Result
RQ1:静态分析器的有效性?
从下图可以看出许多漏洞都不会被这几个静态分析器找到。尤其是在Poppler,FFmpeg和libpng中。作者认为主要是有这几个原因:
- poppler是纯C++程序,静态工具虽然说支持C++,但可能支持得不是很好
- FFmpeg是最大程序,有40多万行的代码。有可能让静态分析器终止分析。
- libpng检测不出来可能是因为他的漏洞比较复杂,fault和erro不在一个函数中。
这些结果看出来,前向导入的漏洞和普通的漏洞差不多,没有什么很明显的差别。
从图6可以看出,各个静态分析器的性能中,商用的那个是最好的,然后是CodeQL,FlawFinder,infer,CodeChecker和CPPCheck。
总结:静态分析器会错过相当多的漏洞。即使是这里表现最好的商业工具,在四个场景中的漏报有47% (S1-1), 70% (S1-2), 64% (S2-1), and 80% (S2-2)
RQ2:静态分析组合能提高多少有效性?
大概提升21%-34%。虽然能找到的漏洞多了,但是也增加了更多的误报。一些单独表现较差的静态分析器,在组合起来还是能够发现其他找不到的漏洞。
RQ3:检测最好和最坏漏洞是哪一类?
主要看第二列这边的图。因为第一列的场景是不管检测的类型正不正确。检测最多的漏洞是CWE664,但是也就50%的可以找到。CWE 682在不考虑漏洞类型的情况下检测最好,说明这些工具判断漏洞类型的部分做得可能不是很好。
CWE 691 707是检测效果最差的。同时很多静态工具并不支持这类漏洞的检测。
Threats To Validity
External Validity : 结果是否可以泛化到其他程序中?为此用了很多各种各样的真实程序,6种静态工具。
Internal Validity:
- CWE mapping的正确性?=》仔细阅读文档来做mapping,不确定的就询问开发者进一步确定。
- 前向导入的漏洞是否会影响静态分析器的性能?=》所以用了20个开源程序,binutils和FFMpeg。结果发现没啥差别。
- 有可能发现别的未知漏洞。但是不妨碍验证静态分析工具的有效性。
- 漏洞的根源和表现在同一个函数里的假设不能确定一定对。但是在这个数据集里的假设基本成立。
相关工作
用真实世界程序验证静态分析器的工作还有一个是OpenSSF CVE Benchmark,主要是针对JavaScript的静态器。他们的benchmark包含3个分析器和200个CVE漏洞。
Zitser 的工作也是评估C/C++静态分析器的性能。不过他们针对的是缓冲区溢出漏洞,同时更看重误报率。
Misha Zitser, Richard Lippmann, and Tim Leek. 2004. Testing Static Analysis Tools Using Exploitable Buffer Overflows from Open Source Code. In Proceedings of the International Symposium on the Foundations of Software Engineering.
zheng 的工作是比较了三个商业的C/C++静态分析器。这三个主要是对Nortel 网络协议软件产品的。他们发现的漏报率比文中的结果要低一些,但也差不多属于同一个梯度。
Jiang Zheng, Laurie Williams, Nachiappan Nagappan, Will Snipes, John P. Hudepohl, and Mladen A. Vouk. 2006. On the Value of Static Analysis for Fault Detection in Software
Chatzieleftheriou and Katsaros也对6个静态分析器做了评估,不过他们使用的是人工合成的数据集。也用到了CPPCheck,效果也很差。
George Chatzieleftheriou and Panagiotis Katsaros. 2011. Test-Driving Static Analysis Tools in Search of C Code Vulnerabilities. In Proceedings of the International Computer Software and Applications Conference
Goseva-Popstojanova and Perhinschi对三个商业的C/C++和JAVA工具做了评估。用的是Juliet Test Suite和两个开源的C软件。总共包含12个真实漏洞。
Katerina Goseva-Popstojanova and Andrei Perhinschi. 2015. On the Capability of Static Code Analysis to Detect Security Vulnerabilities. Information and Software Technology 68 (dec 2015), 18–33
D’abruzzo Pereira and Vieira 也评估了CPPCheck和FlawFinder检测真实漏洞的有效性。不过他们只测评了这两个工具。而且他们判断漏洞是否检测到是看源文件是否被标记出来了,粒度太粗了。
Jose D’abruzzo Pereira and Marco Vieira. 2020. On the Use of Open-Source C/C++ Static Analysis Tools in Large Projects. In Proceedings of the European Dependable Computing Conference. 97–102.
Kaur and Nayyar用10个不同的CWE对C/C++和Java静态分析器做评估。他们用的也是Juliet Test Suite。
Arvinder Kaur and Ruchikaa Nayyar. 2020. A Comparative Study of Static Code Analysis Tools for Vulnerability Detection in C/C++ and JAVA Source Code. In Procedia Computer Science,
Thung 对三个不同的JAVA静态分析器进行评估。他们的benchmark包含200个软件缺陷,但并不是所有都是安全漏洞。他们的结果也很相似,静态分析工具50%也检测不出来。
Ferdian Thung, Lucia, David Lo, Lingxiao Jiang, Foyzur Rahman, and Premkumar T. Devanbu. 2012. To What Extent Could We Detect Field Defects? An Empirical Study of False Negatives in Static Bug Finding Tools. In Proceedings of the International Conference on Automated Software Engineering. ACM,
Habib and Pradel 使用三个JAVA静态分析器对15个真实程序做了评估,发现95.5%的缺陷无法检测到。然而,JAVA工具的结果并不能很好地迁移到C分析器,因为不同语言的构造不同和而且漏洞的类型也不同。
Andrew Habib and Michael Pradel. 2018. How Many of All Bugs Do We Find? A Study of Static Bug Detectors. In Proceedings of the International Conference on Automated Software Engineering. ACM, New York, NY, USA,
可以发现相关工作都比较古老,可见作者的工作还是比较新颖。