wap2.0是一款比较好用的php源代码安全检查工具,可以扫描sql注入,xss跨站漏洞等问题的工具.
前些日子想使用这款工具来进行php代码检查,发现使用-p参数扫描的时候会进行不下去.然后就开始跟源代码.
跟踪源代码后,得出的结论是:
当php源文件中存在中文并且同时出现语法错误,那么antlr3提供的词法解析器就会处于无限循环当中,使得扫描
处于暂停状态,不用-p参数,直接扫描文件也会出现这个问题.
我设立三个解决方案:
1. 修改antlr的源代码, 在遇到中文的时候,可以正确判断,经过两天的努力,宣告失败,原因有两个,一个是我对antlr词法
分析的理解还不够,就是技不如人啊.第二个就是:antlr的源码本来已经很不错,如果我改了这里,会造成正确的词法解析
出现问题.
2. 修改grammars脚本,研究了一天,发现还是不行,这里的g脚本是通用的范本,如果按照我的要求修改了,可能会引起正
常的解析失败.
3. 在上面两个根本性解决方案行不通的时候,我考虑了一个折中的办法,因为中文在php源文件中一般是提示性的语句,
就算没有也不会影响正确的扫描结果,因此,我考虑在进入词法分析前,将文件输入流进行替换,把中文字符替换成空.
下面详细介绍一下这个操作过程,理解之后其实很简单,上代码:
在文件buildAST.java这个类的buildAST构造方法里面,有一句代码如下:
//这里读入要扫描的文件,原来的情况,这个输入流会直接进入后续的分析过程
//System.out.println("final_file::"+final_file);
byte[] temp=getContent(final_file);//这里我定义了一个字节数组,用来存放读入的文件,getContent方法用于把文件按字节读入
byte[] ret=new byte[temp.length];// 这里定义一个新的字节数组,用于存放处理过的数据
if(temp[i]>127 || temp[i]<0){ //如果为汉字,则将这个字节换成空字符 ,否则将这个字符拷贝到ret中
//System.out.println("old::"+(char)temp[i]);
ret[i]=32;
}
else{
ret[i]=temp[i];
//System.out.println("ret::"+(char)ret[i]);
}
}
InputStream in=new ByteArrayInputStream(ret); //利用字节数组输入流,将替换后的数组转换为输入流
// Create input stream from standard input
//ANTLRInputStream input = new ANTLRInputStream(is); 这句是以前的用法,直接读取文件流进入分析
ANTLRInputStream input = new ANTLRInputStream(in);//这里就是替换后的输入流作为参数进入后续的分析过程
经过测试,用-p做参数扫描,可以顺利通过了.而且扫描漏洞结果没有问题
//附上 getContent代码
public byte[] getContent(String filePath) throws IOException {
File file = new File(filePath);
long fileSize = file.length();
if (fileSize > Integer.MAX_VALUE) {
System.out.println("file too big...");
return null;
}
FileInputStream fi = new FileInputStream(file);
byte[] buffer = new byte[(int) fileSize];
int offset = 0;
int numRead = 0;
while (offset < buffer.length && (numRead = fi.read(buffer, offset, buffer.length - offset)) >= 0) {
offset += numRead;
}
// 确保所有数据均被读取
if (offset != buffer.length) {
throw new IOException("Could not completely read file "
+ file.getName());
}
fi.close();
return buffer;
}