sql注入官方解释
SQL注入即是指web应用程序对用户输入数据的合法性没有判断或过滤不严,攻击者可以在web应用程序中事先定义好的查询语句的结尾上添加额外的SQL语句,在管理员不知情的情况下实现非法操作,以此来实现欺骗数据库服务器执行非授权的任意查询,从而进一步得到相应的数据信息
sql注入原理
SQL注入攻击是通过操作输入来修改SQL语句,用以达到执行代码对WEB服务器进行攻击的方法。简单的说就是在post/getweb表单、输入域名或页面请求的查询字符串中插入SQL命令,最终使web服务器执行恶意命令的过程。可以通过一个例子简单说明SQL注入攻击。假设某网站页面显示时URL为http://www.example.com?test=123,此时URL实际向服务器传递了值为123的变量test,这表明当前页面是对数据库进行动态查询的结果。由此,我们可以在URL中插入恶意的SQL语句并进行执行。另外,在网站开发过程中,开发人员使用动态字符串构造SQL语句,用来创建所需的应用,这种情况下SQL语句在程序的执行过程中被动态的构造使用,可以根据不同的条件产生不同的SQL语句,比如需要根据不同的要求来查询数据库中的字段。这样的开发过程其实为SQL注入攻击留下了很多的可乘之机。
sql注入案例
案例1:
比如我们登陆系统 需要输入用户名,密码,正常输入用户名“00000000”,密码“123456”,则校验登陆语句为:
select * from prpduser a where a.usercode='00000000' and a.password='123456'
如果我们在用户名输入 00000000'--
select * from prpduser a where a.usercode='00000000'-- and a.password='123456' ;
相当于把后边查询密码校验直接注释掉,这就造成不需要密码也能登陆系统。
案例二:
比如我们在查较为机密的数据的时候,正常查询sql为:select * from aa where aa.name='张三';
在其中name一栏中输入 张三' or '1'='1
则最终查询sql为: select * from aa where aa.name='赵一' or '1'='1';
最后 or ‘1’=‘1’ 为true,所以就可以得到所有数据;
解决方法
通过过滤器实现
在项目web.xml 中加入 以下代码:
<filter>
<filter-name>sqlFilter</filter-name>
<filter-class>cn.com.cis.acic.sales.common.web.SqlInjectionFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>sqlFilter</filter-name>
<url-pattern>*.do</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>sqlFilter</filter-name>
<url-pattern>*.jsp</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>sqlFilter</filter-name>
<url-pattern>/*Servlet</url-pattern>
</filter-mapping>
编写过滤器:
package cn.com.cis.acic.sales.common.web;
import java.io.IOException;
import java.util.Enumeration;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;
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;
import javax.servlet.http.HttpSession;
public class SqlInjectionFilter implements Filter {
public void init(FilterConfig filterConfig) throws ServletException {
// TODO Auto-generated method stub
}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain filterChain) throws IOException, ServletException {
// TODO Auto-generated method stub
HttpServletRequest req = (HttpServletRequest)request;
HttpSession session = req.getSession();
String UserCode =(String) session.getAttribute("UserCode");
HttpServletResponse res =(HttpServletResponse)response;
String path = req.getContextPath();
//获取所有请求参数
Map paramMap = req.getParameterMap();
String sql = "";
for(Entry e : (Set<Entry>)paramMap.entrySet()){
for(String s:(String[])e.getValue()){
sql = sql+s;
}
}
if(checkIsSQLInjection(sql)){
session.setAttribute("errorInfo", "严重警告:用户"+UserCode+"非法攻击行为:"+sql+"已被记录在案!!!");
request.getRequestDispatcher("/common/errorSql.jsp").forward(req,
res);
return;
}
filterChain.doFilter(req, res);
return;
}
public void destroy() {
// TODO Auto-generated method stub
}
/**
* 检查是否存在sql 注入
* @param sql 待检查的参数
* @return true 存在 sql 注入,false 不存在 sql 注入
*/
protected boolean checkIsSQLInjection(String sql){
//统一转为小写
sql = sql.toLowerCase();
//过滤掉的sql关键字,可以手动添加
String badSql ="create|where|group|select|delete|update|drop|--|from|truncate|and|or ";
//比较全面的关键字
/*String badSql ="and|exec|execute|insert|select|delete|update|count|drop|*|%|chr" +
"|mid|master|truncate|char|declare|sitename|net user|xp_cmdshell|;|or|+|like'|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|//|/|%|#";*/
//避免误杀,排除合法参数
String exculedParam = "sysstandardvalueconfig|sysstandardvalueconfigupdate|sysstandardconfig|teamupdate|" +
"personupdate|userbranchverify|nodeupdateorganizemanage|select|agentcodeandcom|importscore|";
String[] exculedParams = exculedParam.split("\\|");
String[] badSqls = badSql.split("\\|");
//排除合法参数
for(int k=0;k<exculedParams.length;k++){
if(sql.indexOf(exculedParams[k])>=0){
return false;
}
}
//检查注入
for(int i=0;i<badSqls.length;i++){
if(sql.indexOf(badSqls[i])>=0){
return true;
}
}
return false;
}
}