170606、防止sql注入(三)

SpringMVC利用拦截器防止

SQL注入案例一个简单的PHP登录验证SQL注入

比如一个公司有一个用来管理客户的客户管理系统,在进入后台进行管理的时候需要输入用户名和密码。
假设在客户端传给服务器的字段分别为用户名username和密码password,那么如果用来处理登录的服务器端代码对用户的输入做以下处理:
PHPsql注入
上面的PHP代码就是首先获取客户端POST过来的填写在表单里面的用户名和密码,接着要MySQL去执行下面这条SQL语句:

SELECT `id` FROM `users` WHERE `username` = username AND `password` = password;

可以看到上面的代码没有对用户的输入做任何的过滤,这是非常容易遭到黑客攻击的。
比如,一个用户在输入用户名的输入框里面输入了

user’;SHOW TABLES;--

那么就会解析为下面的SQL:

SELECT `id` FROM `users` WHERE `username` = user’;SHOW TABLES;-- AND `password` = password;

可以看到被解析的SQL被拆分为了2条有用的SQL:

(1)SELECT `id` FROM `users` WHERE `username` = user’;
(2)SHOW TABLES;

而后面验证密码的部分就被注释掉了。这样攻击者就轻松的获得了这个数据库里面的所有表的名字。同样的道理,如果攻击者在输入框里面输入:

’;DROP TABLE [table_name];--

那么,这一张表就被删除了,可见后果是非常严重的。
而用户如果在用户名输入框里面输入了:user’or 1=1--
那么会被解析成:

SELECT `id` FROM `users` WHERE `username` = user
or 1=1-- AND `password` = password;

这里可以看到1=1永远为真,这样不用输入用户名就直接可以登入系统了。

一个ASP新闻动态页面的id查询

比如有一个新闻网站的动态页面是这种格式:

http://www.news.com/news.asp?id=100

那么当用户在浏览器的地址框里面输入

http://www.news.com/news.asp?id=100;and user>0

那么如果这个网站的数据库用的是SQL Server的话,那么SQL Server在解析的时候,由于user是SQL Server的一个内置变量,它的值就是当前连接数据库的用户,那么SQL在执行到这里的时候会拿一个类型为nvarchar的和一个int类型的比较。比较过程中就必然涉及类型的转化,然而不幸的是,转化过程并不是一帆风顺,出错的时候SQL Server将会给出类似将nvarchar值”aaa”转为为int的列时发生语法错误。这个时候攻击者就轻松的获得了数据库的用户名。

SpringMVC拦截器防止SQL注入

为了有效的减少以及防止SQL注入的攻击,开发人员在开发的时候一定不要期待用户的输入都是合理的,当用户输入完毕之后,应该严谨的对用户提交的数据进行格式上的检查以及过滤,尽可能的减少被注入SQL 的风险。
一般来说,不同的服务器端语言都有不同的解决方案。比如拿中小型企业采用得最多的PHP语言来说,PHP的官方就为开发者提供了这样的一些函数,比如mysql_real_escape_string()等。
接下来会详细介绍如何通过SpringMVC的拦截器实现防止SQL注入的功能。
这里以我的大数据人才简历库的拦截器为例。

自定义拦截器类实现HandlerInterceptor接口

package com.rick.ssm.common.filter;

import java.util.Enumeration;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

/**
 * -------------------------------------------
 * Title : SqlInjectInterceptor 
 * Description : 防止sql注入拦截器
 * Create on : 2017年8月2日 下午2:43:39
 * Copyright (C) strongunion
 * @author RICK
 * @版本号: V1.0
 * -------------------------------------------
 */
public class SqlInjectInterceptor implements HandlerInterceptor{

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        Enumeration<String> names = request.getParameterNames();
        while (names.hasMoreElements()) {
            String name = names.nextElement();
            String[] values = request.getParameterValues(name);
            for (String value : values) {
                value = clearXss(value);
            }
        }
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
            ModelAndView modelAndView) throws Exception {
        // TODO Auto-generated method stub
        
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
            throws Exception {
        // TODO Auto-generated method stub
        
    }
    
    /**
     * TODO: 处理字符转义
     * @Auhor: RICK
     * @Date : 2017年8月2日
     * @param value
     * @return
     */
    private String clearXss(String value) {
        if (value == null || "".equals(value)) {
            return value;
        }
        value = value.replaceAll("<", "<").replaceAll(">", ">");
        value = value.replaceAll("\\(", "(").replace("\\)", ")");
        value = value.replaceAll("'", "'");
        value = value.replaceAll("eval\\((.*)\\)", "");
        value = value.replaceAll("[\\\"\\\'][\\s]*javascript:(.*)[\\\"\\\']", "\"\"");
        value = value.replace("script", "");
        return value;
    }
}

配置拦截器

<!-- 拦截器配置--> 
<mvc:interceptors>
  <!-- SQL注入拦截-->
  <mvc:interceptor>
    <mvc:mapping path="/**"/>
    <bean class="com.rick.ssm.common.filter.SqlInjectInterceptor"/>
  </mvc:interceptor> 
</mvc:interceptors>

 

posted @ 2017-08-02 14:49  目标奔雷手  阅读(383)  评论(0编辑  收藏  举报