前言
代码安全扫描是指在不执行代码的情况下对代码进行评估的过程。代码安全扫描工具能够探查大量“if——then——”的假想情况,而不必为所有这些假想情况经过必要的计算来执行这些代码。
那么代码安全扫描工具到底应该怎么使用?以下是参考fortify sca的作者给出的使用场景:
常规安全问题(如代码注入类漏洞)这块,目前的fortify sca规则存在较多误报,通过规则优化降低误报。而在特定安全问题上,越来越多的合规要求需要满足(如等保、国信办、银保监要求),自带的扫描规则肯定检测不到这些问题,需要自定义扫描规则,从合规的角度来展示安全风险。
常规安全问题误报优化
目前开发人员反馈最多的问题是:代码安全扫描工具误报较多,我们先看下代码安全安全分析的过程,如下图示:
由于中间编译建模和扫描工具分析的过程是内置在扫描工具里的二进制的可执行程序完成的,我们无法干预,那么只能再在源代码编写、规则定义和扫描结果展示3个地方来操作降低误报,如下将逐项展示:
源代码编写
1. 编码规范
尽量使用fortify官方认可的安全库函数,如ESAPI,使用ESAPI后fortify sca会把漏洞标记为低危,是可以忽略的漏洞类型。以下是对常见漏洞的安全库函数
1).xss
代码语言:javascript复制org.owasp.esapi.Encoder/Encoding/Escapefrom
2). 文件路径操纵
代码语言:javascript复制org.owasp.esapi.getValidDirectoryPathororg.owasp.esapi.getValidFilename
3). SQL注入
代码语言:javascript复制org.owasp.esapi.Encoder.encodeForSQLorg.apache.commons.lang.StringEscapeUtils.escapeSql
4). 命令注入
代码语言:javascript复制org.owasp.esapi.Encoder.encodeForOS
2. 使用注解(针对java)
如果我们用过SonarQube,我们会发现有两种修改代码的方式来解决误报。
注释
在被误判的代码行后面加上注释://NOSONAR
String name = user.getName(); //NOSONAR
注解
在类或方法上面加上 @SuppressWarnings 注解
代码语言:javascript复制@SuppressWarnings("squid:S1309")publicclass Example { ... @SuppressWarnings("all") public void example(){ }}
squid:S1309即是扫描规则编号
同样的fortify sca也有提供注解的功能,Fortify Java Annotations
比如如下代码:
代码语言:javascript复制publicclass User {public finalstatic String PASSWORD_LABEL = "password";privateString userId;privateString userKey;publicvoid printUserData() {System.out.println("Fortify[userId=" userId ", " PASSWORD_LABEL "=" userKey "]");}}
扫描平台会在publicfinal static String PASSWORD_LABEL = “password”报告PasswordManagement:Hardcoded Password漏洞。
使用后
代码语言:javascript复制@FortifyNotPasswordpublicfinal static String PASSWORD_LABEL = "password";@FortifyPasswordprivate String userKey;
不会再报这样的漏洞
可用的注解如下:
FortifyCheckReturnValue FortifyCommandInjectionSink FortifyCommandInjectionValidate FortifyDangerous FortifyDatabaseSource FortifyFileSystemSource FortifyNetworkSource FortifyNonNegative FortifyNonZero FortifyNotNumberPassthrough FortifyNotPassword FortifyNotPrivate FortifyNumberPassthrough FortifyPCISink FortifyPCISource FortifyPCIValidate FortifyPassthrough FortifyPassword FortifyPrivacySink FortifyPrivacyValidate FortifyPrivate FortifyPrivateSource FortifySQLSink FortifySQLValidate FortifySink FortifySource FortifySystemInfoSink FortifySystemInfoValidate FortifyValidate FortifyWebSource FortifyXSSSink FortifyXSSValidate
规则定义
Fortify sca主要对中间代码进行了数据流分析、控制流分析、代码结构分析、内容和配置文件分析。
1.新建规则
这里以fortify安装目录下自带的php示例代码(Samplesbasicphp)为例:
我们在缺陷代码基础上增加了validate函数去做安全净化处理,fortify sca不能识别这个函数的作用。
在函数上右键点击弹出write rules for this function,我们接下来通过图形界面创建数据流跟踪的净化规则
再次扫描后我们发现fortify sca已经可以识别我们自定义的validate函数
打开规则文件xml我们看到taintflag里已经增加了xss安全验证的flag,只要在数据流跟踪中发现validate函数就不会再误报xss问题。
另外新建规则还可以使用fortify自带的自定义用户规则向导,可以通过图形化方式配置40多种规则类型。当然如果还有更高的规则定制要求,就在向导生成的xml基础上进一步更新吧。
2.覆盖规则
以下演示覆盖一个秘钥硬编码的规则:
还是以fortify安装目录下自带的php示例代码(Samplesbasicphp)为例
由于没有加密机和密码托管平台,数据库密码只能明文写在代码或配置文件里,怎么不让fortify重复报出这种问题呢?
写一条新规则覆盖这个id的规则,如下xml:
随便指定一个不会用到的保存秘钥的变量名pasword,覆盖了这条规则
再次扫描发现这个密码硬编码问题已不再提示
3.裁剪规则
Fortify规则是.bin文件,这个是无法直接编辑的,不过可以转成xml,再根据需要裁剪成为customer rules。不过要注意扫描时需要加上–no-default-rules禁用默认规则。
扫描结果展示
1.根据漏洞的可能性和严重性进行分类筛选
我们观察fortify扫描的每一条漏洞,会有如下2个标识,严重性(IMPACT)和可能性(LIKEHOOD),这两个标识的取值是从0.1~5.0,我们可以根据自己的需要筛选展示对应严重性和可能性范围的漏洞,这些漏洞必须修复,其他不严重的或者难以利用的漏洞可以作为中低危漏洞做选择性修复。如果我们的应用是新闻资讯或者体育类应用,那么我们可以把阈值调高,增加漏报率,降低误报率。如果我们的应用是金融理财或交易类应用,那么我们可以把阈值调低,增加误报率,降低漏报率
如果你觉得以上的方法过于粗暴,那么可以再详细看看这个漏洞命中了哪些扫描规则,比如如下规则标识Rule ID,
然后我们在规则文件里查找发现对应Rule ID的3个属性,漏洞准确性accuracy,漏洞严重性IMPACT,漏洞被利用的可能性Probability,取值都是0.1~5.0,我们可以根据需要设置筛选条件,比如仅展示漏洞准确性在4.0以上的漏洞。
那么以上的筛选能不能通过自动化的方式进行呢?当然可以,如果你使用了fortify ssc,那么fortify ssc提供了api接口,可以针对一些你不想要看到的漏洞做屏蔽(suppress)处理。如果你没有使用fortify ssc,那么你只能自己解析fpr文件,更改漏洞审计信息后保存,在github上是有些类似的开源项目可以借鉴的。
2.根据历史的人工漏洞审计信息进行扫描报告合并
如果我们的项目在以前做过fortify sca的扫描,并经过开发人员或安全人员审计,那么历史的审计信息可以沿用,每个漏洞都有一个编号instance ID,已经审计过确认是误报的漏洞是不会重复出现的。报告合并我们可以通过fortify ssc或者fortify sca的命令行或者图形界面操作。
3.利用大数据分析和机器学习做漏洞误报屏蔽
目前这是正在探索的一个方向,但这个方式需要大量可靠的漏洞审计样本,如果样本少的话会很难操作。
安全合规问题规则定制
《互联网个人信息保护指南》里指出重要数据在存储过程中应保密,包括但不限于鉴别数据和个人信息。而我们在实际审查中发现,有的应用为了排查问题方便,在服务器中间件Log里记录了用户的姓名、shenfenzheng号、yinhangka号、手机号等敏感信息。这种问题可以通过自动化代码审查发现,而fortify默认的规则是无法识别shenfenzheng号这种信息的,我们可以新建CharacterizationRule来完成对shenfenzheng标识的识别
1.增加对合规信息的识别
没有自定义规则时,漏掉了对shenfenzheng信息的检测:
写了自定义规则后,漏报问题得以解决:
自定义规则如下:
这样就给shenfenzheng信息加上private的污点标记。这里只是简单演示,详细的规则需要使用正则和语法树分析等。
2.定制漏洞描述和修复建议
我们可以修改每个漏洞详情和修复建议的描述,默认的漏洞详情和漏洞修复建议描述是这样的:
我们可以修改规则,让漏洞详情和修复建议按照我们想要的方式呈现出现。比如漏洞详情里加上这是等保要求、银保监的哪一条要求,一定要修的。
比如修复建议里加上安全组件库的使用推荐,和一些漏洞修复知识库的总结,放在这里比用ppt培训效果要好多了
总结
Fortify sca总体来说一款很强大的代码安全扫描工具,但不可避免的有误报和漏报。我们需要控制误报对开发人员的干扰,同时为了满足合规要求,我们需要定制扫描规则,来完成扫描工具对本地法律法规的适配。
*本文原创作者:随便看看,本文属于FreeBuf原创奖励计划,未经许可禁止转载