2018年1月13日星期六

关于在全自动化代码扫描实现路途中的一些坑和经验总结

2017年9月11日入职公司,到现在已经四个月了,说起来可能连我自己也不太敢相信,公司的安全工作几乎是从零开始的。

从零开始的过程是非常痛苦的,很多该有的东西都是没有的。

比如业务系统中严格的的权限控制,系统展示数据中的脱敏,SDL落地,都是混乱的。

后来与部门的同事一起,做了很多工作,现在已经使公司的安全方面步入了正轨。

代码安全,在信息安全的是极其重要的一部分,直接关系着系统的安全性,在刚开始的时候,我们挑选代码扫描的工具,有很多的选择:
开源的:
Cobra (https://github.com/wufeifei/cobra)
RIPS
Seay的代码审计工具
等等

商业的:
fortify
chechmarx CxSuite
360代码卫士
。。。。等等

公司的大多数项目是基于java语言的,所以,不支持java的排除掉,其次一些便捷性,命令行操作等考察点,经常一段时间的测试后,最后选择了使用fortify来做代码扫描工具。

一开始是同事是想使用jekins+fortify来实现自动化审计,利用jekins的插件来实现对svn、git项目代码的下载更新和对fortify的调用,还有使用jekins自带的命令行来实现对系统的调用,将扫描的结果在web端直接进行展示这样方便开发人员进行修改bug。

在这个方案的调查过程中,发现要想实现的话,需要一个叫fortify ssc的东西,这个东西我无从下手,还有jekins本来也挺臃肿的,耗费机器的性能,研究到一半出现了很多的问题,由于当时时间比较紧迫,也没有再多的研究时间,干脆就使用原始的方法了。

于是出现了方案二,下载git和svn工具做代码管理工具,然后配合fortify进行项目源码审查,然后手工导出报告。

这个方法试行了一段时间,确实是可行的,这个可行的前提是项目不多,代码扫描工作不频繁,但这是不可能的。

一开始是一两个项目,然后是三四个,后来等所有项目出来后统计了一下,大概是二十多个,这些项目的更新时间不定期,有时开发更新的勤快,一天要扫描七八个项目的代码。

从统计到三四个项目开始的时候,原先svn项目的也由于公司要求都转到了git上,于是我就在研究用其它方法来实现代码扫描的自动化,开始的想法是:使用git命令行来实现代码更新,fortify部分使用统一的扫描版本,仅将扫描目录输出日志设置为变量,新项目出来的时候使用此模版进行添加。将这git命令和fortify扫描代码写在一个bat脚本里,每次要更新代码扫描的时候就点击该脚本,就可以实现半自动化了。脚本大致如下流程:

E:
cd E:\javaxiangmu
git pull
set rootdir=E:\javaxiangmu
set logdir=E:\javaxiangmu\scanlog
......(fortify代码扫描过程)
exit

一两次的时候这个脚本还是挺方便的,理想状态下这个方案可行。但是,有时git pull更新是空的,此处并没有阻断代码扫描。于是我又在代码拉取更新后增加手工选择是否进行代码扫描:

E:
cd E:\javaxiangmu
git pull
choice /C yn /M "继续代码审计按y,取消按n."
if errorlevel 2 goto end
if errorlevel 1 goto startcheck
:end
echo -e "Power OFF! Goodbye!\n"
exit
:startcheck
set rootdir=E:\javaxiangmu
......(fortify代码扫描过程)
exit

这样一来,容错性就高了很多

后来我还想着做一个集合脚本,把所有项目的名称、文件夹等信息做成数组存储起来,每次运行脚本后可以选择更新的项目和审计的项目。

不巧的是,在这个阶段,突然多了很多的项目,同时要对这些项目做黑盒+白盒的安全检测,忙到不行了,统一的大脚本就没空写起来。

后来为了直观,我干脆把这个模版拆开了,分成git部分和fortify扫描部分,双击一下就可以运行不同的脚本执行不同的功能。

统一大集合脚本就这样没写了

后来,项目增多,前面的项目也开始要进行第二次扫描,坑爹的是,很多项目这时候要扫描的代码是他们分出来的一些指定分支,如1.0.1release分支,而不是原先默认的master分支了,于是这时候,git部分脚本变成了

E:
cd E:\javaxiangmu
git pull http://gituser:gitpasswd@abcd.com/efg.git 1.0.1release:master
pause

代码更新部分这样写理论上是正确的,但是在实际操作中会有一些代码合并的坑,有时甚至会出现![reject]的情况,这是git的坑,解决方法可以使用-f参数强制合并,或者改变本地git项目对origin主机分支的追踪。

后来,由于开发人员场所迁移,内网通讯工具由于网络还没来得及改造所以不同场所的内网通讯工具无法进行文件传输,好在svn和git仍然两边可以访问,于是这是只能用svn来进行文档传输了,处于安全考虑,这时需要对不同项目进行不同密码的加密。于是,然后再通过svn更新,在自动化实现的逻辑中大概代码流程如下:

cd D:
cd D:\javaxiangmu
ReportGenerator.bat -format pdf -f def.pdf -source abc.fpr -template OWASP2018.xml -user masker
rem winrar部分
rem cd报告导出的地方
winrar -p这是一个密码 a "D:\javaxiangmu\a1.zip" "def.pdf"
rem svn命令行提交部分
cd "D:\svn"
svn add "a1.zip"
svn commit "a1.zip" -m "...."
....(对日志文件的操作)
svn commit
exit

这样就大概是可以实现代码扫描的半自动化的,包括导出pdf报告及后续的同步,但是,后来发现fortify中一个非常坑爹的地方,有一个导出报告的选项中short name是默认勾选的,这意味着每次的报告中的具体出现漏洞的代码都是只说文件名,而不会具体列出是在什么文件夹,这样就给开发造成了非常大的困扰。我找遍fortify的选项和命令行参数都没找到使它能默认不勾选的方法,于是命令行导出pdf这里也只能作罢。

过了几天,网络修复好了,内网通讯工具又可以使用了,所以上面的脚本也被枪毙了。

再后来,开发人员反馈报告中一些是误报和无法修复的问题,这种操作无法在命令行实现,所以只能手工进行屏蔽折叠这些误报点,我一个人对接了二十多个系统,查看他们误报反馈,再进行重新扫描,忙到飞起。

再然后,所有的代码扫描工作基本有了正常的流程,
开发人员通知我修复情况和误报情况,告诉我修复后的代码在什么分支,我看情况选择git命令更新他们的代码,然后再进行自动化扫描,扫描完我再在fortify AWB里对他们的反馈情况进行扫描结果调整,最后在导出pdf报告给他们。

虽然我仍执着于全自动化的代码扫描,但是以目前的情况看,有很多点是影响着我的全自动化的,首先是git分支的问题,虽然我已让开发们都各自开一个codescan分支给我专门进行代码扫描,但是目前只有三四个是这样做的,其它大多是还是需要沟通然后我每次git pull更新他们指定的分支,git pull又可能会出现一些合并的问题,这里就不说git pull会遇到哪些坑了;其次是误报反馈的问题的,这点只能手工屏蔽;再者是fortify的short name问题,至今我也没找到控制该选项的按钮或参数,能使它不默认出现。当然在这探索的过程中其实还有很多小坑,就不再列举了。

在想着实现自动化代码扫描的过程中,我对git、svn和fortify的了解越来越深,也对SDL概念越加清晰,企业内部的安全涉及方方面面,我们都任重而道远。

我仍然想着实现代码扫描的全自动化,我相信,这些问题都是可以解决的,而我,有一天会漂亮的解决掉这些问题。

文章最后感谢我的公司,给予我这个舞台,感谢领导对我的信任和重视,让我负责公司所有项目的代码扫描和渗透测试工作,感谢同事的帮助和配合,互相进步。

没有评论:

发表评论