使用方法
GUI入口
如果有GUI,直接运行ScanWizard,按照步骤点下去就行了,结束后会在项目文件夹下生成Fortify{ProjName}的bat或sh文件,运行即可开始扫描,结束后会生成Fortify{ProjName}.fpr文件,双击打开可以查看漏洞和检查报告。
Java项目
如果是java项目,生成项目时会提示项目缺少依赖,如下图所示:
不能解析的类会严重影响扫描效果(见下文),因此一定要指定第三方依赖位置,但是现在很多项目采用Maven或者Gradle构建,此时除了手工指定lib目录外,还可以通过下面Maven和Gradle项目插件的扫描方法
Maven项目
若为maven项目,先在.../Fortify/Fortify_SCA_and_Apps_{version}/plugins/maven
文件夹下找到maven-plugin-bin.zip
解压,然后maven clean install
安装到本地仓库:
1 | unzip maven-plugin-bin.zip -d /tmp/maven-plugin-bin |
然后在用ScanWizard时第二步,勾选Maven,再简单配置一下maven即可
Gradle项目
gradle没有图形化入口,怎么用见“CLI入口”章节
加依赖和不加依赖的效果对比
这里对比一下未加依赖和添加依赖后/用maven插件的扫描结果,用java-sec-code测试,从左到右依次为未加依赖(src),手工指定lib目录(lib)和maven插件(maven)
可以看到再高危漏洞这里,不加依赖漏掉了XSS、PathManipulation和SQL注入的缺陷,并且在中危和低危漏洞方面的缺陷检出率也远低于加依赖的结果(注意到手动指定lib的中危缺陷比maven插件的多一个,实际上是在lib中有一个缺陷重复了两次)
CLI入口(只针对java)
GUI虽然好用,但是CLI入口更方便我们封装做二次开发。
看一下官方的手册或者分析一下GUI生成的脚本,可以得知fortify扫描主要分为一下几步
Extracting Arguments File,生成参数列表,保存到Fortify{ProjName}.sh.args文件中,参数报刊了java的classpath(-cp),java版本,排除目录,待扫描的目录,由于命令行长度限制所以需要单独保存成文件,生成的实例文件如下(
FortifyXXX.sh.args
):1
2
3
4
5
6
7"-cp"
"/home/anemone/all_my_work/whitebox_scanner/downloads/graphql_java_gen-master/support/build/libs/support-0.2.1-sources.jar:/home/anemone/all_my_work/whitebox_scanner/downloads/graphql_java_gen-master/support/build/classes/java/test:/home/anemone/all_my_work/whitebox_scanner/downloads/graphql_java_gen-master/support/build/libs/support-0.2.1-javadoc.jar:/home/anemone/all_my_work/whitebox_scanner/downloads/graphql_java_gen-master/support/build/libs/support-0.2.1.jar"
"-source"
"1.8"
"-exclude" "/home/anemone/all_my_work/whitebox_scanner/downloads/graphql_java_gen-master/**/*.jar"
"-exclude" "/home/anemone/all_my_work/whitebox_scanner/downloads/graphql_java_gen-master/**/*.class"
"/home/anemone/all_my_work/whitebox_scanner/downloads/graphql_java_gen-master"Cleaning previous scan artifacts,即清除上一次扫描
1
sourceanalyzer -Xmx14237M -Xms400M -Xss24M -b buildXXX -clean
Translating files,即编译文件到中间语言
1
sourceanalyzer -Xmx14237M -Xms400M -Xss24M -b buildXXX @FortifyXXX.sh.args
Testing Difference between Translations,不是太清楚这一步是做啥的
Starting scan,开始扫描
1
sourceanalyzer -Xmx14237M -Xms400M -Xss24M -b buildXXX -scan -f result.fpr
那么提炼一下,最简单的命令应该就是:
1 | sourceanalyzer -Xmx14237M -Xms400M -Xss24M -b buildXXX -clean |
特别的,maven项目:
1 | sourceanalyzer -b buildxyz mvn clean compile |
Gradle项目:
1 | sourceanalyzer -b buildxyz gradle clean build . |
原理浅析
Fortify使用文档中介绍了其使用的分析器,这里给大家翻译一下
Buffer
缓冲区溢出分析器,可以显示数据流
Configuration
配置分析器,用来分析项目中的错误配置
Content
HTML内容分析器,除了分析HTML外还会分析PHP,JSP和ASP文件
Control Flow
控制流分析器,用来检测潜在危险的操作序列。通过分析程序中的控制流路径,控制流分析器确定一组操作是否按一定的顺序执行。例如,控制流分析器检测未初始化变量,XML是否正确配置。
Data Flow
数据流分析器,应该是最常见也是效果最好的分析器了。通过污点传播技术,检测用户输入(source)是否会传播到危险函数(sink)点中,一般的XSS、SQLI都是这个分析器扫描出来的。
Higher Order
不知道咋翻译,为动态语言设计的数据流分析器,用来应对高阶函数编程而设计的分析器,高阶函数编程在动态语言(如python,js和swift)中很常见,具体来说即使用匿名表达式生成函数,而该分析器就要跟踪这些匿名函数的数据流。
Semantic
语义分析器,用来发现不安全的函数使用,例如java被废弃的方法和C/C++中的gets()
Structural
结构分析器,不是很清楚原理,文档中说其用来分析死代码,未被声明为static的logger等
与Find-sec-bugs对比
find-sec-bugs算是一个比较出名的开源java代码审计工具了,这里对比一下扫描质量,还是拿java-sec-code来比较,java-sec-code一列数字表示真实API数/安全API数,其他两扫描器列数字表示检出真实漏洞数/误报数,结合这几个数据可以算出漏报和误报率。
java-sec-code | Fortify | Find-sec-bugs | |
---|---|---|---|
CommandInject/RCE | 2+1=3/1 | 3/1 | 3/1 |
CORS | 3/1 | 1/1 | 2/1 |
Deserialize | 2/0 | 0/0 | 1/1 |
Fastjson | 1/0 | 0/0 | 0/0 |
FileUpload | 1/1 | 1/2 | 1/2 |
IP Forge | 1/1 | 0/0 | 0/0 |
Java RMI | 1/0 | 0/0 | 0/0 |
JSONP | 4/1 | 0/0 | 0/0 |
XXE+OOXML+ XLSX+XStream | 9+1+1+1=12/8 | 6/0 | 6/0 |
PathTraversal | 1/1 | 1/1 | 1/1 |
SpEL | 1/0 | 1/0 | 1/0 |
SQLi | 3/4 | 3/0 | 1/0 |
SSRF | 8/1 | 5/1 | 3/1 |
SSTI(velocity) | 1/0 | 1/0 | 1/0 |
URL Redirect | 3/2 | 2/1 | 3/1 |
URL whitelist Bypass | 5/3 | 0/0 | 0/0 |
XSS | 2+4(ssrf)=6/1 | 6/4 | 0/0 |
总体对比下来,fortify不是很占优势,主要区别在于反射型XSS——Fortify检测到6个而Find-sec-bugs没有检测到,SSRF——Fortify多检出2个,但这些差异估计是由于规则导致的,给Find-sec-bugs增加一些source和sink点就能够弥补。
另外,Find-sec-bugs发现两处密码硬编码而Fortify未发现: