场景: WEB程序容易被SQL注入攻击,攻击原理是在请求参数中传入非法字符,造成SQL语句出现出现异常情况,已达到攻击者想要的结果。
分析: 一般的攻击者都是在传入的请求参数上做文章,所以我们重点检查的是request的参数,判断request请求参数是否有非法字符,及数据库关键字,如果有即判定为SQL注入,否则通过。一般在WEB应用中都采用FILTER技术来处理此类问题,以下类适用于ORACLE,其他数据库请修改SqlInjectFilter类中的static{ }内的关键字。
新增功能: 验证POST攻击,精简验证列表,优化验证框架
解决:
1. 配置FILTER,配置位置为 /WEB-INF/web.xml
说明:
1.
2. 这里判定是否启用,默认是启用,否则将
3. 这是判定SQL注入后跳转的页面,根据实际情况修改
2. 新建FILTER类: SqlInjectFilter ; 2. 配置FILTER
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.util.Vector;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.io.IOUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
*
* @ClassName: SqlInjectFilter
* @Description: TODO V2.0
* @author fasake [email protected]
* @date 2012-12-20 下午8:53:34
*
*/
public class SqlInjectFilter implements Filter {
protected Log log = LogFactory.getLog(getClass());
protected static Vector list = new Vector();
protected String enabled = "true";
protected String failthPath = "/TaxWeb/failth.jsp";
public void destroy() {
// TODO Auto-generated method stub
}
public void doFilter(ServletRequest arg0, ServletResponse arg1,
FilterChain arg2) throws IOException, ServletException {
// TODO Auto-generated method stub
HttpServletRequest httpServletRequest = (HttpServletRequest) arg0;
HttpServletResponse httpServletResponse = (HttpServletResponse) arg1;
//获取GET方法请求参数串
String queryString = httpServletRequest.getQueryString();
//是否启动,web.xml中配置的初始化参数
if (enabled.equalsIgnoreCase("true")) {
//开始XSS(METHOD:GET)和sql注入检测
boolean isXssFind = false;
if(queryString!=null && !queryString.equalsIgnoreCase("null")){
String src = java.net.URLDecoder.decode(queryString,"GB2312");
src += "_"+queryString;
if(src!=null && !src.equalsIgnoreCase("null")){
String keyword = "";
for (int i = 0; i < list.size(); i++) {
keyword = list.get(i).toString();
if(src.indexOf(keyword)!=-1){
isXssFind = true;
break;
}
}
if(isXssFind){
log.error("发现疑为跨站脚本攻击,检测判断请求地址包含非法字符:"+java.net.URLEncoder.encode(keyword,"GB2312"));
httpServletRequest.setAttribute("errorMsg", "发现疑为跨站脚本攻击,检测判断请求地址包含非法字符:"+java.net.URLEncoder.encode(keyword,"GB2312"));
httpServletRequest.getSession(true).setAttribute("injectKey","发现疑为跨站脚本攻击,检测判断请求地址包含非法字符:"+java.net.URLEncoder.encode(keyword,"GB2312"));
httpServletRequest.getSession().invalidate();
httpServletResponse.sendRedirect(failthPath);
throw new java.lang.IllegalAccessError();
}
}
}
//开始XSS(METHOD:POST)和sql注入检测
if(!isXssFind){
arg2.doFilter(new RequestWrapperXSS(httpServletRequest,httpServletResponse,list,failthPath), arg1);
}
}else{
arg2.doFilter(arg0, arg1);
}
}
/**
* 初始化
*/
public void init(FilterConfig arg0) throws ServletException {
// TODO Auto-generated method stub
enabled = arg0.getInitParameter("enabled");
failthPath = arg0.getInitParameter("failthPath");
if (enabled == null || "".equals(enabled)) {
enabled = "true";
}
if (failthPath == null || "".equals(failthPath)) {
enabled = "/TaxWeb/failth.jsp";
}
log.info("SQL注入检测初始化完成");
}
static {
list.add("'");
list.add("(");
//list.add("or");
//list.add("and");
list.add("[");
list.add("<");
list.add(".."+File.separator);
// 请求参数不能能有脚步
list.add("script");
list.add("+");
//list.add("-");
list.add("*");
list.add("%");
}
}
/**
*
* @ClassName: RequestWrapperXSS
* @Description: TODO 自定义HttpServletRequest
* @author fasake [email protected]
* @date 2012-12-20 下午7:16:00
*
*/
class RequestWrapperXSS extends HttpServletRequestWrapper {
protected Log log = LogFactory.getLog(getClass());
private HttpServletRequest request;
private HttpServletResponse serlvetResponse;
private boolean isXssFind=false;
private Vector keywords;
private String failForwardPath;
public RequestWrapperXSS(HttpServletRequest servletRequest) {
super(servletRequest);
this.request = servletRequest;
}
/**
*
* @param servletRequest
* @param serlvetResponse
*/
public RequestWrapperXSS(HttpServletRequest servletRequest,HttpServletResponse serlvetResponse) {
super(servletRequest);
this.request = servletRequest;
this.serlvetResponse = serlvetResponse;
}
public RequestWrapperXSS(HttpServletRequest servletRequest,HttpServletResponse serlvetResponse,Vector keywords,String failForwardPath) {
super(servletRequest);
this.request = servletRequest;
this.serlvetResponse = serlvetResponse;
this.keywords = keywords;
this.failForwardPath = failForwardPath;
}
/**
* 覆盖
*/
public String[] getParameterValues(String name){
String[] values = super.getParameterValues(name);
//log.debug("parameter name: "+name+" value:"+values.toString());
try {
xssCheck(values,keywords);
} catch (IllegalAccessError e) {
// TODO Auto-generated catch block
e.printStackTrace();
throw e;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return values;
}
/**
* 覆盖
*/
public String getParameter(String para){
String postStrInfo = super.getParameter(para);
//log.debug("parameter name: "+para+" value:"+postStrInfo);
try {
//log.debug("parameter name: "+para);
log.debug("(检测)接收到的["+request.getMethod()+"]请求参数值: " + postStrInfo);
xssCheck(postStrInfo,keywords);
} catch (IllegalAccessError e) {
// TODO Auto-generated catch block
e.printStackTrace();
throw e;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return postStrInfo;
}
public ServletInputStream getInputStream() {
//ServletInputStream
ServletInputStream stream = null;
//POST表单信息
String postStrInfo = null;
try{
stream = request.getInputStream();
byte[] buffer = IOUtils.toByteArray(stream);
postStrInfo = new String(buffer,"GB2312");
//拆分请求参数串
String[] args = postStrInfo.split("\r\n");
for (int i = 0; i < args.length; i++) {
String line = args[i];
//过滤分隔符,和请求参数名称
if(line.trim().startsWith("-------------------") || line.trim().startsWith("Content-Disposition") || line.trim().equals("")){
log.debug("(忽略)接收到的["+request.getMethod()+"]请求参数值: " + line);
continue;
}
log.debug("(检测)接收到的["+request.getMethod()+"]请求参数值: " + line);
xssCheck(line,keywords);
}
//验证完成
final ByteArrayInputStream bais = new ByteArrayInputStream(buffer);
//生成新的ServletInputStream
ServletInputStream sis = new ServletInputStream() {
public int read() throws IOException {
// TODO Auto-generated method stub
return bais.read();
}
};
stream = sis;
}catch(IOException e){
e.printStackTrace();
}
return stream;
}
/**
* @Title: xssCheck
* @Description: TODO 检测XSS和SQL注入处理类
* @param @param postStrInfo
* @param @throws IOException
* @param @throws IllegalAccessError
* @return void
* @throws
*/
private void xssCheck(String postStrInfo,Vector array) throws IOException,
IllegalAccessError {
if(postStrInfo==null)return;
String src = postStrInfo==null?"null":postStrInfo.toLowerCase();
src = java.net.URLDecoder.decode(src,"GB2312");
//验证XSS中是否包含相关关键字
if(src!=null && !src.equalsIgnoreCase("null")){
String keyword = "";
for (int i = 0; i < array.size(); i++) {
keyword = array.get(i).toString();
if(src.indexOf(keyword)!=-1){
isXssFind = true;
break;
}
}
if(isXssFind){
log.error("发现疑为跨站脚本攻击,检测判断请求地址包含非法字符:"+java.net.URLEncoder.encode(keyword,"GB2312"));
request.setAttribute("errorMsg", "发现疑为跨站脚本攻击,检测判断请求地址包含非法字符:"+java.net.URLEncoder.encode(keyword,"GB2312"));
request.getSession(true).setAttribute("injectKey","发现疑为跨站脚本攻击,检测判断请求地址包含非法字符:"+java.net.URLEncoder.encode(keyword,"GB2312"));
request.getSession().invalidate();
serlvetResponse.sendRedirect(failForwardPath);
throw new java.lang.IllegalAccessError();
}
}
}
/**
*
* @Title: xssCheck
* @Description: TODO 检测XSS
* @param @param values
* @param @param array
* @param @throws IOException
* @param @throws IllegalAccessError
* @return void
* @throws
*/
private void xssCheck(String[] values,Vector array) throws IOException,IllegalAccessError {
if(values==null){return;}
for (int j = 0; j < values.length; j++) {
String src = java.net.URLDecoder.decode(values[j],"GB2312");
//验证XSS中是否包含相关关键字
if(src!=null && !src.equalsIgnoreCase("null")){
String keyword = "";
for (int i = 0; i < array.size(); i++) {
keyword = array.get(i).toString();
if(src.indexOf(keyword)!=-1){
isXssFind = true;
break;
}
}
if(isXssFind){
log.error("发现疑为跨站脚本攻击,检测判断请求地址包含非法字符:"+java.net.URLEncoder.encode(keyword,"GB2312"));
request.setAttribute("errorMsg", "发现疑为跨站脚本攻击,检测判断请求地址包含非法字符:"+java.net.URLEncoder.encode(keyword,"GB2312"));
request.getSession(true).setAttribute("injectKey","发现疑为跨站脚本攻击,检测判断请求地址包含非法字符:"+java.net.URLEncoder.encode(keyword,"GB2312"));
request.getSession().invalidate();
serlvetResponse.sendRedirect(failForwardPath);
throw new java.lang.IllegalAccessError(); }
}
}
}