关于Mybatis的SQL注入


前言:最近在学Mybatis,趁机把Mybatis框架下可能引发的SQL注入来过一遍,加深理解

Mybatis传递数据有两种方式,一种是#{},还有一种是${},而#{}基本能防止SQL注入,但是某些环境下需要用到${},所以可能就会导致SQL注入的产生

大概产生SQL注入的有如下几种类型,自己都会详细的记录,以及自己的思考

1、模糊查询like

2、in之后的参数

3、order by

数据表userinfo的数据如下:

模糊查询like

Mapping.xml

    <!--like下的SQL注入-->
    <select id="getUserByName" parameterType="String" resultType="com.zpchcbd.pojo.User">
        select * from userinfo where name like "%"#{name}"%"
    </select>

业务代码:

    public static void test06(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        List<User> userList = userMapper.getUserByName("六");
        for (User user : userList) {
            System.out.println(user);
        }
        sqlSession.close();
    }

首先一开始想要实现先试试如下

select * from userinfo where name like '%#{name}%'

发现会报错,它根本识别不了索引值来进行替换

那么如果将SQL语句改成如下为,发现能正常的查询出数据!

select * from userinfo where name like '%${name}%'

发现用${}来执行的SQL语句,最终的SQL语句为如下,也就是只是单纯的替换了,连预编译的工作都没有进行处理!

select * from userinfo where name like '%六%'

如果我们此时加一个单引号则会出现报错!

到目前则证明了如果使用${},则是使用拼接SQL语句的方法,那么就会造成SQL注入,但是如果想要预防SQL注入试图通过#{}来写,又会发生报错!

所以对于模糊查询like的SQL注入就是这样子产生的,一般人就会使用${}来进行查询,修复方法就是自己还需要手动加一层过滤才行

自己又想了下那么如果SQL语句是这样呢?select * from userinfo where name like "%"#{name}"%"

发现它是可以查询的,并且会进行预编译操作,最终的SQL语句为如下:select * from userinfo where name like "%"'六'"%";,这种自己没见过,猜想是不是在mysql中可能就是单引号和双引号会自动进行拼接?那这种可以作为一种绕过方法吗?还需要去研究或者有懂的人可以告知下!

到这里,我们其实就可以明白了${} #{} 本质到底做了什么事,${}这个东西就是我们正常在写SQL语句中的进行拼接的操作,这种是十分可能引起SQL注入的,然而#{}则是经过预编译的操作,其实也就是一个占位符?,预编译会自动给你两边加上单引号,并且对其中的非法字符进行转义操作,最终预防了SQL注入的产生!

但是一旦跟业务挂钩之后,SQL注入就十分容易的产生!

in之后的参数

继续来in的SQL注入

Mapper.xml

    <select id="getUserById" resultType="com.zpchcbd.pojo.User">
        select * from userinfo where id in (${id})
    </select>
    // getuser by id
    public static void test02(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        //方式一
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        List<User> userList = mapper.getUserById("1,2,3");
        for (User user : userList) {
            System.out.println(user);
        }
        sqlSession.close();
    }

先是传递"1,2,3",发现在#{}的情况下也可以正常查询,但是只能查询到一条,原因同样是预编译的影响,最终的SQL语句为select * from userinfo where id in ('1,2,3')

当改成${}的时候,则最终查询的记录为3条,SQL语句为:select * from userinfo where id in (1,2,3)

所以才会导致SQL注入的产生,其实都是跟业务挂钩

order by

参考之前写过的:https://www.cnblogs.com/zpchcbd/p/14725943.html

官方文档对${}和#{}的介绍:https://mybatis.org/mybatis-3/zh/sqlmap-xml.html

参考文章:https://mp.weixin.qq.com/s?__biz=MjM5OTk2MTMxOQ==&mid=2727827368&idx=1&sn=765d0835f0069b5145523c31e8229850&mpshare=1&scene=1&srcid=0926a6QC3pGbQ3Pznszb4n2q


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM