JavaWeb开发防止SQL、XSS注入

时间:2021-07-09 11:50:28

SQL注入简介

SQL注入是比较常见的网络攻击方式之一,它不是利用操作系统的BUG来实现攻击,而是针对程序员编程时的疏忽,通过SQL语句,实现无帐号登录,甚至篡改数据库。

SQL注入攻击实例

比如在一个登录界面,要求输入用户名和密码:

可以这样输入实现免帐号登录:

用户名: ‘or 1 = 1 –

密 码:

点登陆,如若没有做特殊处理,那么这个非法用户就很得意的登陆进去了.(当然现在的有些语言的数据库API已经处理了这些问题)

这是为什么呢? 下面我们分析一下:

从理论上说,后台认证程序中会有如下的SQL语句:

String sql = "select * from user_table where username=

' "+userName+" ' and password=' "+password+" '";

当输入了上面的用户名和密码,上面的SQL语句变成:

SELECT * FROM user_table WHERE username=

'’or 1 = 1 -- and password='’

分析SQL语句:

条件后面username=”or 1=1 用户名等于 ” 或1=1 那么这个条件一定会成功;

然后后面加两个-,这意味着注释,它将后面的语句注释,让他们不起作用,这样语句永远都能正确执行,用户轻易骗过系统,获取合法身份。

这还是比较温柔的,如果是执行

SELECT * FROM user_table WHERE

username='' ;DROP DATABASE (DB Name) --' and password=''

….其后果可想而知…

应对方法

1、配置web.xml


 <!--过滤XSS注入 -->
  <filter>
    <filter-name>XssEscape</filter-name>
    <filter-class>com.cm.contract.filter.XSSFilter.XssFilter</filter-class>
  </filter>
  
  <filter-mapping>
    <filter-name>XssEscape</filter-name>
  <url-pattern>/*</url-pattern>
  <dispatcher>REQUEST</dispatcher>
  </filter-mapping>
  <!--过滤SQL注入 -->
  <filter>  
     <filter-name>SqlFilter</filter-name>  
     <filter-class>com.cm.contract.filter.SQLFilter.SqlFilter</filter-class>  
   </filter>  
   <filter-mapping>  
       <filter-name>SqlFilter</filter-name>  
       <url-pattern>/*</url-pattern>  
   </filter-mapping>   


2、SqlFilter.java

package com.cm.contract.filter.SQLFilter;
import java.io.IOException;
import java.util.Enumeration;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
* 过滤sql关键字的Filter
* @author FengArWei

*/
public class SqlFilter implements Filter {

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {

HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse res = (HttpServletResponse) response;
//获得所有请求参数名
@SuppressWarnings("rawtypes")
Enumeration params = req.getParameterNames();

String sql = "";
while (params.hasMoreElements()) {
//得到参数名
String name = params.nextElement().toString();
//System.out.println("name===========================" + name + "--");
//得到参数对应值
String[] value = req.getParameterValues(name);
for (int i = 0; i < value.length; i++) {
sql = sql + value[i];
}
}
//System.out.println("============================SQL"+sql);
//有sql关键字,跳转到error.html
if (sqlValidate(sql)) {
res.sendRedirect("error.html");
//String ip = req.getRemoteAddr();
} else {
chain.doFilter(req, res);
}
}

//效验
protected static boolean sqlValidate(String str) {
str = str.toLowerCase();//统一转为小写
String badStr = "'|and|exec|execute|insert|create|drop|table|from|grant|use|group_concat|column_name|" +
"information_schema.columns|table_schema|union|where|select|delete|update|order|by|count|*|" +
"chr|mid|master|truncate|char|declare|or|;|-|--|+|,|like|//|/|%|#";//过滤掉的sql关键字,可以手动添加
String[] badStrs = badStr.split("|");
for (int i = 0; i < badStrs.length; i++) {
if (str.indexOf(badStrs[i]) !=-1) {
return true;
}
}
return false;
}

public void init(FilterConfig filterConfig) throws ServletException {
//throw new UnsupportedOperationException("Not supported yet.");
}

public void destroy() {
//throw new UnsupportedOperationException("Not supported yet.");
}
}
3、XssFilter.java

package com.cm.contract.filter.XSSFilter;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;

public class XssFilter implements Filter {

@Override
public void init(FilterConfig filterConfig) throws ServletException {
}

@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
chain.doFilter(new XssHttpServletRequestWrapper((HttpServletRequest) request), response);
}

@Override
public void destroy() {
}
}
4、XssHttpServletRequestWrapper.java

package com.cm.contract.filter.XSSFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;

import org.apache.commons.lang3.StringEscapeUtils;

public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {

public XssHttpServletRequestWrapper(HttpServletRequest request) {
super(request);
}

@Override
public String getHeader(String name) {
return StringEscapeUtils.escapeHtml4(super.getHeader(name));
}

@Override
public String getQueryString() {
return StringEscapeUtils.escapeHtml4(super.getQueryString());
}

@Override
public String getParameter(String name) {
return StringEscapeUtils.escapeHtml4(super.getParameter(name));
}

@Override
public String[] getParameterValues(String name) {
String[] values = super.getParameterValues(name);
if(values != null) {
int length = values.length;
String[] escapseValues = new String[length];
for(int i = 0; i < length; i++){
escapseValues[i] = StringEscapeUtils.escapeHtml4(values[i]);
}
return escapseValues;
}
return super.getParameterValues(name);
}

}

总的说来,防范一般的SQL注入只要在代码规范上下点功夫就可以了。

凡涉及到执行的SQL中有变量时,用JDBC(或者其他数据持久层)提供的如:PreparedStatement就可以 ,切记不要用拼接字符串的方法就可以了