近期打算做一个插件化的白盒静态代码安全审计自动化平台和黑盒网站安全审计自动化平台。现在开源或半开源做黑盒网站安全扫描的平台,大多是基于python脚本,安全人员贡献python脚本插件增强平台功能。对自己或身边开发人员,对java语言更熟悉,为了后期维护打算采用java写一个这样的平台。另外白盒代码安全扫描也有Fortify等收费软件,或依赖PMD做代码分析,不过比如新增了什么安全问题,需要自定义或扩展就比较麻烦。

比如一个简单的:现在用struts2存在漏洞,现在需要升级到2.3.28版本,于是我写一个插件,判断pom.xml里如果有配置struts2,只要版本不是2.8.2就认为存在漏洞。平台提供下载制定SVN或GIT或其他服务器的代码,然后执行该插件即可扫描哪些项目有问题了。

该项目最近几天和同事一起做了一个初步版本,想法还有不完善的地方,作为后期参考,主要目的是先搭建一个能用的架子出来。

首先提供插件,那就需要有一个独立的jar项目作为插件依赖的接口项目,它需要定义插件的接口和交互的对象,接口需要至少2个方法:验证该插件是否可扫描,执行插件逻辑扫描,比如白盒扫描插件接口定义如下:

public interface IWhiteboxService {
/**
* 验证该文件是否符合规则需求
*
* @param inputFile
* 被扫描的文件信息
* @return 验证结果
*/
ValidateResult validate(InputFile inputFile); /**
* 如果validate验证通过,则开始扫描
*
* @param inputFile
* 被扫描的文件信息
* @return 扫描结果
*/
List<ScanResult> scan(InputFile inputFile);
}

  然后需要有一个统一的服务,用于调用插件执行代码扫描。通过网站或定时任务只需要调用该服务即可。后面可以做扫描任务只扫描哪些插件,比如扫描所有插件代码:

	public void scan(Whitetask task) {
//todo:循环插件扫描。或后期根据任务和插件关闭表扫描
if (null == task || StringUtil.isNull(task.getCodepath())) {
//todo:记录日志,任务表有问题
return;
}
/*
* 1、读取whiteplugin表所有插件并缓存插件对应的代码,不用每次反射
* 2、循环task.getCodepath()路径下所有文件,默认java文件,根据getFileext()的文件类型和getExcluderule()排除的文件而定
* 根据循环后的文件存储到LIST集合里,循环时排除文件是为了减少LIST的内容
* 3、根据循环LIST结果再循环所有文件,调用插件的代码进行扫描
* 4、扫描结果插入whitescanresult表
* 5、循环完毕后,修改whitetask表的当前任务扫描完毕
*/
List<Whiteplugin> allPlugins = whitepluginService.getAll();
if (null == allPlugins || allPlugins.size() < 1) {
//todo:记录日志,没有可用的插件
return;
}
List<WhitePluginData> allPluginDatas = null;
if (null != allPlugins) {
allPluginDatas = WhitePluginGenerator.generate(allPlugins);
}
if (null == allPluginDatas || allPluginDatas.size() < 1) {
//todo:记录日志,有插件,转换失败
return;
}
List<FileData> fileDatas = FileGenerator.generate(task.getCodepath(), task.getFileext(), task.getExcluderule());
doScan(fileDatas, allPluginDatas, task);
}

  真正扫描的doScan方法:

	public void doScan(List<FileData> fileDatas, List<WhitePluginData> allPluginDatas, Whitetask task) {
if (null == fileDatas || null == allPluginDatas || fileDatas.size() < 1 || allPluginDatas.size() < 1) {
return;
}
for (int i = 0; i < fileDatas.size(); i++) {
//循环每个文件调用每个插件
FileData tempFileData = fileDatas.get(i);
for (int j = 0; j < allPluginDatas.size(); j++) {
//循环每个插件
IWhiteboxService whiteboxService = allPluginDatas.get(j).getWhiteboxService();
InputFile inputFile = new InputFile();
inputFile.setContents(tempFileData.getContent());
inputFile.setFileExt(FileUtil.getEXT(tempFileData.getFileName()));
inputFile.setFileName(tempFileData.getFileName());
//todo:这里传递的是绝对路径,不是包路径
inputFile.setPackagePath(tempFileData.getPath());
List<InputFileContent> inputFileContents = getFileContents(tempFileData.getContent());
inputFile.setFileContents(inputFileContents); ValidateResult validateResult = whiteboxService.validate(inputFile);
if (null != validateResult && validateResult.isIssuccess()) {
List<ScanResult> scanResults = whiteboxService.scan(inputFile);
if (null != scanResults && scanResults.size() > 0) {
//插入数据库
for (int z = 0; z < scanResults.size(); z++) {
Whitescanresult whitescanresult = getScanResult(inputFile, scanResults.get(z), allPluginDatas.get(j), task);
whiteScanResultService.save(whitescanresult);
}
}
}
}
}
}

  根据插件扫描完成后,把结果插入扫描结果表。核心的表结构包括任务表、插件表、扫描结果表,相关主要表字段如下:

DROP TABLE IF EXISTS `vulfeel`.`whiteplugin`;
CREATE TABLE `vulfeel`.`whiteplugin` (
`ID` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(200) DEFAULT '' COMMENT '插件名称',
`type` tinyint(4) DEFAULT NULL COMMENT '后期扩展分类',
`importlevel` tinyint(4) DEFAULT NULL COMMENT '插件重要性,1轻微,2一般,3重要',
`classpath` varchar(2000) DEFAULT NULL COMMENT '插件包路径,比如com.xx.vulfeel.plugin.a',
`filename` varchar(200) DEFAULT NULL COMMENT 'class名称或jar名称,如果插件是jar包则是jar包名称,比如a.jar;否则是class名称,比如a.class',
`functions` varchar(2000) DEFAULT NULL COMMENT '插件功能描述',
`version` varchar(200) DEFAULT NULL COMMENT '插件版本',
`refurl` varchar(1000) DEFAULT NULL COMMENT '插件原理参考URL等内容',
`userid` int(11) DEFAULT NULL COMMENT '插件提供者用户ID',
`createtime` datetime DEFAULT NULL,
`remark` varchar(2000) DEFAULT NULL COMMENT '插件其他备注',
PRIMARY KEY (`ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='白盒扫描插件表'; DROP TABLE IF EXISTS `vulfeel`.`whitescanresult`;
CREATE TABLE `vulfeel`.`whitescanresult` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`taskid` int(11) DEFAULT NULL COMMENT '关联任务表ID',
`pluginid` int(11) DEFAULT NULL COMMENT '关联问题插件ID',
`impactlevel` tinyint(4) DEFAULT NULL COMMENT '影响程度,1轻微,2一般,3重要,主要和插件表的importlevel关联',
`classpath` varchar(2000) DEFAULT NULL COMMENT '插件包路径,比如com.xx.vulfeel.plugin.a',
`filename` varchar(200) DEFAULT NULL COMMENT 'class名称或jar名称,如果插件是jar包则是jar包名称,比如a.jar;否则是class名称,比如a.class',
`startline` int(11) DEFAULT NULL COMMENT '问题开始代码行',
`stopline` int(11) DEFAULT NULL COMMENT '问题结束代码行',
`createtime` datetime DEFAULT NULL,
`remark` varchar(2000) DEFAULT NULL COMMENT '其他备注',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='白盒扫描结果表'; DROP TABLE IF EXISTS `vulfeel`.`whitetask`;
CREATE TABLE `vulfeel`.`whitetask` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(200) DEFAULT NULL COMMENT '任务名称',
`codepath` varchar(1000) DEFAULT NULL COMMENT '代码路径,不依赖SVN还是GIT等,只需要传入代码地址即可',
`fileext` varchar(200) DEFAULT NULL COMMENT '扫描的文件格式,默认java文件,逗号分隔,比如:java,js',
`excluderule` varchar(1000) DEFAULT NULL COMMENT '不扫描的路径规则,::两个冒号分割正则,比如:.*test::js$::css$',
`status` tinyint(4) DEFAULT NULL COMMENT '任务状态,1初始任务,2正在执行,3任务正常结束,4任务异常结束',
`userid` int(11) DEFAULT NULL COMMENT '关联创建任务的用户ID',
`createtime` datetime DEFAULT NULL,
`lastmodifytime` datetime DEFAULT NULL,
`remark` varchar(2000) DEFAULT NULL COMMENT '其他备注',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='白盒扫描任务';

  建立任务后,只需要点击执行扫描,即可根据插件扫描出结果,查看结果:

比如一个简单的扫描sql注入的插件扫描结果如上,插件代码如下:

public class SqlInjectPlugin implements IWhiteboxService {

	@Override
public ValidateResult validate(InputFile inputFile) {
// TODO Auto-generated method stub
ValidateResult result = new ValidateResult();
result.setIssuccess(false);
if (null == inputFile || null == inputFile.getFileContents()) {
return result;
}
if (inputFile.getPackagePath().contains("dao")) {
result.setIssuccess(true);
} return result;
} @Override
public List<ScanResult> scan(InputFile inputFile) {
// TODO Auto-generated method stub
List<ScanResult> result = new ArrayList<ScanResult>();
ScanResult scanResult = new ScanResult();
if (null == inputFile || null == inputFile.getFileContents()) {
return result;
}
Pattern pattern = Pattern.compile("(\"[^\"]+\"|\\w+)\\s*(\\+|\\+=)\\s*\\w+");
if (inputFile.getPackagePath().contains("dao")) {
//只扫描包路径有dao的文件
//循环inputFile的每一行,如果有拼接sql就说明存在注入
for (int i = 0; i < inputFile.getFileContents().size(); i++) {
InputFileContent inputFileContent = inputFile.getFileContents().get(i);
Matcher matcher = pattern.matcher(inputFileContent.getContent());
if (matcher.find()) {
scanResult.setStartline(inputFileContent.getLine());
scanResult.setStopline(inputFileContent.getLine());
scanResult.setRemark("存在sql拼接!");
result.add(scanResult);
}
}
}
return result;
} }

  现在项目主要是搭建一个架子,web黑盒扫描的架子也类试,白盒扫描现在是静态代码扫描,没有用PMD等对代码生成语法树分析等,还非常简单。后面有时间再完善和扩展。

如需要转载请注明来自:http://lawson.cnblogs.com/

JAVA语言搭建白盒静态代码、黑盒网站插件式自动化安全审计平台的更多相关文章

  1. java 子类、父类中静态代码块、字段,非静态代码块、字段以及构造函数的初始化顺序和次数

    一个类中的数据初始化顺序是面试官非常喜欢出的面试题之一,本文用一个实例来介绍java中子类.父类中静态代码块.字段,非静态代码块.字段以及构造函数的执行顺序和次数. 一.包结构

  2. 白盒静态自动化测试工具:FindBugs使用指南

    目 录     1     FINDBUGS介绍     2     在ECLIPSE中安装FINDBUGS插件     3     在ECLIPSE中使用FINDBUGS操作步骤     3.1   ...

  3. java面试基础题------》Java 中的父子类静态代码块,代码块,构造方法执行顺序

    4.指出下面程序的运行结果. class A { static { System.out.print("1"); } public A() { System.out.print(& ...

  4. java静态类、静态方法、静态代码块,静态变量及实例方法,实例变量初始化顺序及内存管理,机制

    1.当一个类被第一次使用时,它需要被类加载器加载,而加载过程涉及以下两点: (1)在加载一个类时,如果它的父类还未被加载,那么其父类必须先被加载: (2)当类加载到内存之后,按照在代码中的出现顺序执行 ...

  5. Java接口以及匿名内部类,静态代码块

    接口 接口中只能定义public并且是final的公共静态常量,不允许定义变量. 抽象类可以定义抽象方法和非抽象方法,接口中只能定义公共的,抽象的实例方法. 接口只能由其他接口实现继承 子接口继承的目 ...

  6. 【Java面试题】16 静态代码块,main方法,构造代码块,构造方法

    public class HelloB extends HelloA{ public HelloB() { System.out.println("HelloB"); } { Sy ...

  7. Java面试题之类的静态代码块和静态属性等的加载顺序

    如以下面试题: /** * @author hjs * @date 2019/3/62:41 * @Dec */public class B { public static B t1 = new B( ...

  8. Java父类与子类中静态代码块 实例代码块 静态变量 实例变量 构造函数执行顺序

    实例化子类时,父类与子类中的静态代码块.实例代码块.静态变量.实例变量.构造函数的执行顺序是怎样的? 代码执行的优先级为: firest:静态部分 second:实例化过程 详细顺序为: 1.父类静态 ...

  9. Javascript的一种代码结构方式——插件式

    上几周一直在做公司的webos的前端代码的重构,之中对javascript的代码进行了重构(之前的代码耦合严重.拓展.修改起来比较困难),这里总结一下当中使用的一种代码结构——插件式(听起来怎么像独孤 ...

随机推荐

  1. Zabbix监控

    安装zabbix首先需要安装Nginx+Mysql+PHP,然后再安装zabbix 安装zabbix1:创建用户及组: groupadd zabbix useradd -g zabbix zabbix ...

  2. Nodejs事件引擎libuv源码剖析之:请求(request)结构的设计剖析

    声明:本文为原创博文,转载请注明出处.         在libuv中,请求(request)代表一个用户向libuv发出的指令,比如uv_connect_s就表示一个tcp的连接请求.uv_work ...

  3. 基于fastweixin的微信开发环境搭建(一)

    由于公司业务需要,开发微信版本,才开始接触微信公众平台.在github折腾了几天,试过好几个微信sdk,最终选择fastweixin.个人觉得这个框架还是值得使用的,使用也简单.那么问题来了,很多人想 ...

  4. eclipse配置tomcat

    1eclipse默认是用workspace的comcat,要把它配置成我们自己的外部tomcat,并且发布路径修改为webapps 2设置tomcat的启动和关闭时间 3如果要发布到tomcat根目录 ...

  5. javac -encoding utf8 in linux

    由于另外负责编码的同事用的是utf-8,我用的默认的编码格式gbk,在提交代码时,为了迁就他,我打算把格式用工具转成utf-8. 转化成果后,然后在make一下,发现javac -encoding u ...

  6. java实现二叉树

    栈在遍历的时候不能使用for循环,因为他的size函数在动态变小.

  7. XML基础

    什么是XML? XML(Extensible Markup Language)可扩展标记语言,是一种以简单文本格式存储数据的方式. 它最重要的组成部分是XML元素,包含了文档的实际数据. XML的几个 ...

  8. windows7设置开机启动方式

    打开计算机(资源管理器)(快捷键win+e),输入 C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Startup 将需要开机启动的软件的快捷 ...

  9. python raise a string exception is deprecated

    python不允许raise 一个内建的string 对象.所以就崩溃,可以先将其转换成其他string,比如赋值.

  10. eclipse软件创建servlet

    网上找了好多资料,eclipse创建servlet后,发到tomcat下发布,不能编译,生产class文件. 很多回答的都是一知半解,太气人了,看书.把资料找了一天,才发现是没有servlet-api ...