前言:最近在学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

