源代码静态分析工具(SAST)作为软件安全的重要保障工具,已经在各个领域被广泛使用。随着开源SAST工具的广泛使用,工具种类的增加,使用者很难判断工具的优劣及适不适合企业的应用场景,本文从金融、互联网企业最常用的Java语言代码分析的角度,对静态分析进行一次简要的测评,为大家选择静态分析工具提供依据,此外,本文分析了目前静态代码分析工具存在的技术问题及工具评估的基本准则。
一般来说,误报和漏报率是SAST最重要的技术评价指标,但由于没有通用意义上的测试集能够全面反应静态分析工具在检测精度能力方面高低暨分析的敏感度。由此,为了简化测试难度,本次测评我们选择了一个Java语言且偏安全的国际通用测试集OWASP benchmark,以反应代码分析工具在Java安全检测能力上的强弱。
OWASP基准测试是一个示例应用程序,其中包含来自11个类别的数千个漏洞。基准测试中包括很难通过静态分析处理的代码片段,例如:间接调用、不可达分支、映射、依赖于配置文件的值。
用例下载地址:https://github.com/OWASP/Benchmark/releases,可以在一定程度上反应代码分析工具的检测能力。
1. 测试依据
下表为某款工具的OWASP检测结果,如图所示,左侧一列表示所有类别,P/N为正/负样本数(badcase/goodcase),TP/FP为真/假阳性的数量(badcase报出数/误报数),TN/FN是真/假阴性的数量(good case报出数/漏报数),TPR和FPR是正确率和误报率,Y是约登指数,约登指数( Youden’s indx,YI)即正确指数,此指数值的范围只从0~1,约登指数越大, 其真实性亦越好。其中TPR、FPR、Y的计算公式如下:
TPR=TP/P
FPR=FP/N
Y=[TP/(TP+FN)+TN/(FP+TN)]-1
2. 测试结果
选取市场上主流的SAST工具进行测试,本次选取的测试工具涵盖较广,包含国外商业工具、开源工具以及国内自研工具。如SonarQube[1]代码自动审查工具,该工具是开源工具中使用最多的工具,因为开源免费尤其受很多金融企业喜爱;以色列的Checkmarx CxSAST[2],Micro Focus Fortify[3],目前在电力、金融等行业推广较多,是中国市场Java应用最多的工具之一;还有在互联网领域应用的比较广泛的新思科技的Coverity[4]、IBM Appscan[5]。军工领域应用比较广泛的Parasoft的JTest[6]、VeraCode[7]等。下图是10款静态分析工具的OWASP基准测试结果。商业SAST工具01-06包括:Checkmarx CxSAST、Micro Focus Fortify、IBM AppScan Source、Coverity Code Advisor、Parasoft Jtest、SourceMeter[9]和Veracode工具。
从上图可知,覆盖率指数最大为1(即100%覆盖,不存在漏报);而误报率最低的指数为0.12,最高为0.58,尚无。
静态代码分析基本原理:首先将源代码解析为抽象语法树;采用控制流分析、多态分析、指向分析、函数调用分析等多种分析算法对基本分析模型;考虑路径敏感等多种情况,建立符号执行、抽象解释、图可达性等程序模型;根据缺陷模式在程序模型的基础上生成一阶逻辑表达式并采用SMT进行可满足性约束求解,生成最终结果。目前很多工具只做基本分析层面,尤其是开源工具,针对全模式的敏感分析很多工具并不支持,或支持的不好,因此可能产生大量的误漏报,下面分析了几种典型的问题:
基于以上要点,分析误报原因,了解工具的局限性。通过分析,误报基本由以下几种情况导致。
1. 集合覆盖问题
在集合中,部分集合数据存在污染数据,当检索集合中未污染部分时,导致整个集合覆盖污染,误报产生。如:以下代码中,map中填充带有一个污点(param)和一个未污点的值(a_value),并且从映射中检索参数赋值给bar。如果一个集合的一部分被污染了,假设整个collection都被污染,那么在本例中,当我们检索集合的未污染部分时,导致误报。
private class Test {
public String doSomething(String param) throws ServletException, IOException {
String bar = "safe!";
java.util.HashMap map831 = new java.util.HashMap();
map831.put("keyA-831", "a_Value"); // put some stuff in the collection
map831.put("keyB-831", param); // put it in a collection
map831.put("keyC", "another_Value"); // put some stuff in the collection
bar = (String)map831.get("keyB-831"); // get it back out
bar = (String)map831.get("keyA-831"); // get safe value back out
return bar;
}
} // end innerclass Test
.getClassLoader());
String[] args = {cmd};
String[] argsEnv = { bar };
Runtime r = Runtime.getRuntime();
try {
Process p = r.exec(args, argsEnv, new java.io.File(System.getProperty("user.dir")));
org.owasp.benchmark.helpers.Utils.printOSCommandResults(p, response);
} catch (IOException e) {
System.out.println("Problem executing cmdi - TestCase");
throw new ServletException(e);
}
}
3. 分支问题
在条件分支中,由于条件设置问题,导致某些分支可能永远无法执行,若工具无法判定某些无法执行的分支,可能导致误报的产生。如:在以下代码中,因为num为常量106,(7*18)+num的值永远大于200,导致bar的值始终都为常量字符串,“This_should_always_happen”。另外一个包含污染数据的分支“param”永远无法执行。导致工具产生误报。
private class Test {
public String doSomething(String param) throws ServletException, IOException {
String bar;// Simple ? condition that assigns constant to bar on true condition
int num = 106;
bar = (7*18) + num > 200 ? "This_should_always_happen" : param;
return bar;
}
}
全面、高效地静态识别漏洞,减少工具的误报是静态分析中至关重要的技术,目前在该领域中,仍然有很大的进步空间。针对本次OWASP的基准测试,在选取的工具中,目前结果最好的工具覆盖率可以达到100%,且同时误报率为12%,也说明了工具正不断趋于成熟,但该结果仅针对OWASP测试用例。在后续的静态代码分析技术中,需要不断对静态数据流跟踪器进行持续优化,以此提高检测精度。
为了更好地对代码分析工具进行评价,笔者提出了几个评价维度,并给出评价等级:
评价指标 | 描述 | Level 1 | Level 2 | Level 3 |
---|---|---|---|---|
约登指数 | 查全率-误报 | 0.9-1.0 | 0.7-0.9 | 0.7- |
吞吐量 | 最大检测代码规模 | 1000W+ | 100W+ | 10W+ |
检测效率 | 每小时代码检测代码行数 | 100W+ | 50W+ | 10W+ |
片段代码检测能力 | 能否在编译不通过情况下检测 | 支持所有语言 | C/C++,Java | 不支持 |
并发检测能力 | 支持单CPU的多并发测试 | 硬件允许的最大值 | 单进程 | 单进程 |
跨语言及框架分析能力 | 支持最新的框架及兼容语言间调用 | 支持70种以上框架 | 支持10种以下 | 不支持 |
支持语言 | 支持检测的语言种类 | 20种+ | 10种+ | 3种+ |
与Devops集成能力 | 是否与DevOps主要工具集成 | 支持持续集成工具、版本管理及测试工具,三个方面 | 仅支持版本管理 | 不支持 |
CWE模式覆盖数 | 覆盖的缺陷模式个数 | 200+ | 100+ | 50+ |
最后
【相关资料详细】
网站声明:如果转载,请联系本站管理员。否则一切后果自行承担。
添加我为好友,拉您入交流群!
请使用微信扫一扫!