你需要知道Fortify的使用
使用Fortify的原因有两个,一是作为甲方公司,对于业务使用不同类型的代码或框架编写的程序,要有一个基础的风险识别能力;二是对于我们主要的业务,要有白盒扫描规则的定制化能力。
而Fortify有着多种语言的基础扫描规则,且提供了不同类型的规则定制接口,足以满足我们的需求。所以今天就简单介绍一下如何使用Foritfy扫描、如何对扫描结果进行审计并生成报告,以及一个简单的定制化规则的编写。
01简介
Fortify SCA(Fortify Static Code Analyzer),是一个提供静态源码扫描能力的工具,也是Fortify中的一个核心模块。我们今天只介绍Fortify SCA模块,对于服务端SSC等,单从扫描能力来说,并不是我们关心的重点。下面所说的Foritify也都是在指这个模块。
如果需要了解Fortify支持的编程语言,我们可以打开Fortify的审计窗口。选择Options->Options...->Security Content Management后,可以看到如下窗口:
上面两个框中的是Fortify自带的规则类型以及我们自定义的规则类型,我们在扫描代码时,可以选择使用部分规则,或者全部规则。最下面的框中是我们选择的Fortify规则的语言。目前我们选择的是使用中文,这样扫描和审计代码时,Fortify会使用中文显示命中的漏洞规则的原理和简介。
如果要了解,具体有哪些规则项,我们可以打开下面的网址查看,可以看到规则列表和每条规则的详细介绍。
https://vulncat.fortify.com/zh-cn/weakness
如果想要找到对应的规则文件,可以在Fortify安装目录下的Core\config\rules找到。如果你有自定义的规则,则可以在Core\config\customrules中发现。
02扫描与审计
上面简单的介绍了Fortify的基础信息,接下来,我们介绍一下如何使用。使用的最重要环节,就是扫描。这里我们介绍一下如何对Android项目进行扫描和审计,然后介绍一个使用Fortify扫描PC端Qt项目的例子。
扫描Android项目
使用插件扫描是一个比较推荐的方式,因为操作简单,且环境可靠不需要重新配置。
第一步肯定是获取插件,我们需要从安装Fortify开始。如果已经安装了也不要紧,直接点击安装到原有目录即可,Fortify会自动适配的。安装步骤基本都使用默认选项,但是在选择组件的环节,我们要记得勾选上我们需要的插件。
上图中第一个红框是给Android Studio使用的插件,是本小节需要使用到的。第二个红框则是一个Visual Studio的插件,后面会用到,这里可以先勾选一下(但要记得Visual Studio的插件只能在Visual Studio已存在时安装,版本也不要选错)。安装后,可以在Fortify安装目录下的plugins\IntelliJAnalysis目录中找到我们需要的插件。
然后是第二步,将插件安装到Android Studio上。在Android Studio中打开插件的界面,选择下图中的红框中的图标,然后选择Install Plugin from Disk...选项,选中前面说到的插件文件。然后重启Android Studio即可生效。
生效后我们可以在Android Studio的标题栏中找到Fortify选项,在Fortify->Analysis Settings...选项中,我们可以配置该插件扫描源码的规则和配置。
最后,我们点击Fortify->Analyze Project选项,即可扫描项目并在项目的根目录生成fpr文件
审计
Fortify扫描后生成的fpr文件,就是我们审计的目标。Fortify会将源码信息和识别到的风险记录下来,再加上Fortify自动生成的扫描参数和系统信息,一起以zip格式打包到fpr文件中,如果想要查看详细信息,可以使用zip格式解压fpr文件,这里不再详述。
使用Fortify Audit Workbench打开文件后,可以看到如下视图:
左上角的小窗口会列出所有识别出来的潜在风险,双击即可查看对应位置代码。这里是一个在日志中打印IMEI的风险项,左下角可以看到整个数据链路,了解数据的传递路径。视图中上位置是代码窗口,可以看到已经将危险代码标识出来。如果代码窗口中的中文显示乱码,往往是因为Fortify默认的解析字节码是GBK,可以在选中代码文件后,点击Edit->Set Encoding...选项,设置正确的编码方式即可。中下位置则是对于规则的介绍,协助安全工程师确定问题,识别风险。右侧的则是所有依赖的代码的路径。
在我们审计过程中,如果发现问题是误报,可以右键风险项,选择
Hide in AWB,即可隐藏误报问题。
如果需要再次查看,可以在Options中选择展示。
然后是生成报告,我们可以选择生成两种报告:
BIRT是统计报告,可以按照不同标准显示各种类型风险的统计信息。也可以选择一些我们认定是误报的项,是否显示。
Legacy表示信息的留存,该报告会将各风险项的信息依次打印出来,可以提供给业务确认风险。
扫描Qt项目
该小节是对于一个非Android项目,我们如何使用Fortify扫描,以满足业务需求的简单介绍。
Fortify对于C++类型的代码扫描需要结合编译指令实现,但Fortify支持的C++指令并不多,所以有些类似使用Qt工具开发的项目就需要做一定调整来适配Foritfy的扫描。使用gcc或者cl级别的命令来实现会很麻烦,因为需要对于Qt的qmake工具运行逻辑有一定深入分析,熟知其生成的Makefile以来的环境和make工具,难度较大,所以更建议以Visual Studio的Fortify插件为入口,先将Qt项目转成Visual Studio项目,再使用插件扫描,这样就会容易很多。
我们简单介绍一下流程:
1、在Visual Studio中安装Qt Visual Studio Tools插件和Fortify插件。
2、在Qt插件的Qt Options选项中配置编译套件,该套件位置可以在Qt对应版本下面,比如Qt\Qt5.12.8\5.12.8\msvc2017。
3、使用Qt插件的Open Qt Project File (.pro)...打开对应的Qt项目,并使用插件的Convert custom build steps to Qt/MSBuild选项,将项目转成vs项目,并生成对应的.vcsproj文件。
测试能成功运行后,就可以使用Fortify进行扫描了。步骤类似与上面的Android项目,即可生成对应的fpr文件。另外,如果想要使用命令来自动化的进行项目扫描,但不知道一个类型的项目如何进行适配,可以解压使用插件生成的fpr文件。查看其中audit.fvdl文件中的sun.java.command属性内容,里面包含了该项目生成扫描中间文件的指令参数,可以参考了解如何配置自动化的扫描平台。
03自定义规则
使用Fortify的自定义规则工具,可以让我们直接利用Fortify的强大引擎,较为方便的实现我们定制化的需求。
数据流规则介绍
Fortify提供了包括结构化规则、数据流规则、控制流规则、内容和配置规则等,我们使用数据流规则来构建一个扫描空Intent问题的自定义规则。
首先我们要了解,数据流规则是以对数据流进行污染标记为核心的,从入口增加标记、在过程转换标记、最后在目标点判断标记,并爆发问题为一个完整链路。Fortify中给出了描述污染标记的名词,TaintFlag。下面介绍一下其中会涉及到的几个规则:
1、DataflowEntryPointRule和DataflowSourceRule均为入口。DataflowEntryPointRule用于程序的启动入口,比如C语言程序的main函数;DataflowSourceRule则用于非程序启动的数据入口,比如Android程序获取Intent。作为入口,他们的职责是给输入的数据增加污染标记,比如对于getIntent获得Intent对象,可以增加一个TaintFlag。TaintFlag是可以自定义的,也可以使用已有规则的,我们后面再介绍。
2、DataflowPassthroughRule和DataflowCleanseRule是用于过程转换的规则,我们可以对于数据流向的一些关键函数做一些控制,用于对于数据的标识进行修改。DataflowPassthrough用于做一些精细的判断,用于调整标记,比如一个数据流被标记了5个不同类型的TaintFlag,我们可以在这里换成3个;DataflowCleanseRule则是对于所有标记进行清除,效果比较直接。
3、DataflowSinkRule则是一个数据流的目标点,在这里会识别数据流当前的标记情况,如果符合爆发规则,则爆出问题点。比如对字符串直接进行equals的调用,如果字符串为空则会抛异常。
以上是一个数据流中主要的规则介绍,可以发现还有一个重要概念就是TaintFlag。我们在创建数据流规则的时候,里面会存在一些模板,对于不同类型的规则,他们会使用已经预定义的TaintFlag,达到和Fortify自带规则的适配共用。如果我们不适用TaintFlag,则数据流就相当于是没有使用TaintFlag分类,那么可能会触发到很多不该处罚的场景产生误报。所以我们要使用自定义的TaintFlag,需要自己声明:
实现一个扫描实例
首先我们打开自定义规则工具,即Fortify安装目录下的bin/CustomRulesEditor.exe工具。然后选择File->Generate Rule...选项。
选择Generic Source Rule创建入口规则:
选择针对规则针对的语言:
选择规则针对的函数信息,这里也可以使用正则表达式进行匹配:
选择该入口污染的数据,我们选择返回值。如果选择Argument的话,0表示第一个参数,依次类推即可:
最后选择规则的保存位置:
我们使用xml试图查看规则,可以看到如下内容:
这里我们手动增加了NULLINTENT标记,用于该入口可能会引发的问题类型。
然后我们要生成问题爆发点的规则,这次选择Generic Data Sink Rule规则:
然后是同样的选择规则针对的语言,再选择问题的定级信息:
选择爆发点:
选择要判断数据是否被污染的目标:
最后是一样的选择规则的保存目标,我们可以获得如下Sink规则。
我们同样对于Sink规则,手动增加对于数据流的TaintFlag的判断,是否存在NULLINTENT标记,如果存在,即爆出问题。我们将规则文件放到Fortify的制定位置,即可在扫描使用使用该规则:
效果如下:
总结
这里对于规则的举例并不全面,主要是介绍工具的使用和规则组合的思路。Fortify将规则的入口、过程和爆发分成了不同部分,用于更加方便的对于一个数据流进行扫描。比如Fortify中自带的,对于日志打印敏感数据的规则,可以对于获取IMEI、定位、手机号等不同的信息都加上同样的标记,并在日志打印中对于是否是敏感信息进行判断,就可以将多个入口数据流在一个数据流爆发点爆发。甚至是多个入口对应多个爆发点的情况,也可以通过合理的标记分配来实现。
End