zoukankan      html  css  js  c++  java
  • mybatis的sql中使用$会出现sql注入示例

    mybatis的sql中使用$会出现sql注入示例:

    模拟简单登录场景:

    页面代码:

    function login(){
        //sql注入
        var user = {
            username : "'李雪雷3' or 1=1",
            password : "'ab0715'",
        }
        $.ajax({
            url: '/api/test/login.json',
            type: "POST",
            data: JSON.stringify(user),//将对象序列化成JSON字符串
            dataType: "json",
            contentType : 'application/json;charset=utf-8', //设置请求头信息
            async: false,
            success: function (result) {
                debugger;
                $("#dis").html(result.data);
            },
            error: function (xhr, ajaxOptions, thrownError) {
                debugger;
                alert("出错了");
            }
        })
    }
    <input type="button" onclick="login()" value="登录" name="sunmitBtn">

    controller:

    @RequestMapping("/login")
        @ResponseBody
        public BaseResponse login(HttpServletRequest request, HttpServletResponse response, @RequestBody UserParam userParam){
            try{
                User user = userService.selectByCon(userParam);
                if(user != null){
                    return BaseResponse.successCustom().setData("登录成功").build();
                }
                return BaseResponse.successCustom().setData("登录失败").build();
                //return BaseResponse.successCustom().setData(returnVal).build();
            }catch (Exception e){
                e.printStackTrace();
                return BaseResponse.failedCustom("系统异常").build();
            }
        }

    service接口:

    User selectByCon(UserParam userParam);

    service实现类:

    @Override
        public User selectByCon(UserParam userParam) {
            User user = userMapper.selectByCon(userParam);
            return user;
        }

    mapper接口:

    User selectByCon(UserParam userParam);

    mapper.xml文件:
    使用$的sql:

    <select id="selectByCon" resultMap="BaseResultMap">
        select
        <include refid="Base_Column_List" />
        from user2
        where 1=1
        <if test="username != null" >
          and username = ${username}
        </if>
        <if test="password != null" >
          and password = ${password}
        </if>
      </select>

    数据库用户表user2数据:

    运行程序:
    编译后的sql:

    SELECT
        username,
        PASSWORD
    FROM
        user2
    WHERE
        1 = 1
    AND username = '李雪雷3'
    OR 1 = 1
    AND PASSWORD = 'ab0715'

    执行结果:

    登录成功:

    利用了sql注入漏洞骗过了口令从而登录成功。在账号正确的前提下,密码不管输入什么都能成功登录。

    说明:

    如果使用$写的sql,我们可以利用sql注入漏洞来进行攻击。如果进行表的删除及数据修改sql注入,而数据库没有备份数据,那将是毁灭性的。

    =============================================

    使用#的sql:

    <select id="selectByCon" resultMap="BaseResultMap">
        select
        <include refid="Base_Column_List" />
        from user2
        where 1=1
        <if test="username != null" >
          and username = #{username}
        </if>
        <if test="password != null" >
          and password = #{password}
        </if>
      </select>

    运行程序:
    编译后的sql:

    SELECT
        username,
        PASSWORD
    FROM
        user2
    WHERE
        1 = 1
    AND username = ?
    AND PASSWORD = ?

    加入参数,翻译过来就是:

    SELECT
        username,
        PASSWORD
    FROM
        user2
    WHERE
        1 = 1
    AND username = "'李雷雷3' or 1=1"
    AND PASSWORD = "'ab0715'"

    执行结果:

    说明:

    使用#的sql进行了预编译,用?接受参数。如果是字符串的参数,则使用" "双引号括起来,有效防止了sql注入。

    =========================================

    补充:

    预编译的好处:

    在执行SQL命令时,有二种选择:可以使用PreparedStatement对象,也可以使用Statement对象。

    而熟悉JDBC编程的大侠们都会选择使用PreparedStatement对象,主要因为使用预编译对象PreparedStatement时,有以下几个优点:

    1、效率高

     PreparedStatement可以尽可能的提高访问数据库的性能,我们都知道数据库在处理SQL语句时都有一个预编译的过程,而预编译对象就是把一些格式固定的SQL编译后,存放在内存池中即数据库缓冲池,当我们再次执行相同的SQL语句时就不需要预编译的过程了,只需DBMS运行SQL语句。所以当你需要执行Statement对象多次的时候,PreparedStatement对象将会大大降低运行时间,特别是的大型的数据库中,它可以有效的也加快了访问数据库的速度。

     

    2、大大提高代码的可读性和可维护性

    例如我们在向数据库插入数据:

    一种是使用Statement对象

       java.sql.Statement   stmt=conn.createStatement();

      stmt.executeUpdate("insert into student (name,id,number,count) values ('"+var1+"','"+var2+"',"+var3+",'"+var4+"')");   另一种是使用PreparedStatement对象

    String  sql ="insert into student values(null,?,?,?)";

    java.sql.PreparedStatement pstmt=conn.preparedStatement(sql);

    pstmt.setString(1,var1); pstmt.setString(2,var2); pstmt.setString(3,var3); pstmt.setString(4,var4); pstmt.executeUpdate();

    使用占位符?代替

    将参数与SQL语句分离出来,这样就可以方便对程序的更改和延续,同样,也可以减少不必要的错误。

     

    3、开源防止SQL注入最主要的

    什么时候使用预编译语句?

       一般是在需要反复使用一个SQL语句时才使用预编译语句,预编译语句常常放在一个fo r或者while循环里面使用,通过反复设置参数从而多次使用该SQL语句。为了防止SQL注入漏洞,在某些数据操作中也使用预编译语句。

  • 相关阅读:
    成功率最高的发送邮件代码
    更改ReSharper的智能提示
    [转]SQL 2000 Insert返回自动编号id三种方法比较
    得到汉字的拼音首字母
    不能正确显示UltraWebGrid的解决方法.
    [转]asp.net使用json
    [转] 技术是一种加速器 但重要的不是技术
    [原]模仿Google首页的PNG动画效果
    一个通过DataSet操作XML的类
    C# partial 关键字详解
  • 原文地址:https://www.cnblogs.com/super-chao/p/8421505.html
Copyright © 2011-2022 走看看