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

Posted super超人

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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注入漏洞,在某些数据操作中也使用预编译语句。

 

以上是关于mybatis的sql中使用$会出现sql注入示例的主要内容,如果未能解决你的问题,请参考以下文章

MyBatis如何防止SQL注入

Mybatis面试题

Mybatis的sql注入拦截

mybatis系列-sql注入

mybatis 拦截器

mybatis防止sql注入