文章目录
前言
Mybatis注入留在了Spring后,因为感觉用Spring搭建web端后再进行注入比较贴合实际一些。
测试环境
Mysql:5.7
Springboot:2.1
mybatis:3.5
数据库
创建了一个测试用的数据库Mybatis
CREATEDATABASE/*!32312 IF NOT EXISTS*/`mybatis`/*!40100 DEFAULT CHARACTER SET utf8 */;USE`mybatis`;-- ------------------------------ Table structure for users-- ----------------------------DROPTABLEIFEXISTS`users`;CREATETABLE`users`(`uid`int(10)NOTNULLAUTO_INCREMENT,`uname`varchar(10)CHARACTERSET utf8 COLLATE utf8_unicode_ci NULLDEFAULTNULL,`uage`int(10)NULLDEFAULTNULL,PRIMARYKEY(`uid`)USINGBTREE)ENGINE= MyISAM AUTO_INCREMENT=4CHARACTERSET= utf8 COLLATE= utf8_unicode_ci ROW_FORMAT = Dynamic;-- ------------------------------ Records of users-- ----------------------------INSERTINTO`users`VALUES(1,'Sentiment',20);INSERTINTO`users`VALUES(2,'Shelter',20);INSERTINTO`users`VALUES(3,'Tana',18);
SQL注入的四种方式
这里用的Springboot环境,配置文件较多,先放出关键文件,最终项目放在后边
#{}和${}
接口
List<User>selectOne(@Param("uname")String uname);
配置
<selectid="selectOne"resultType="user">
select * from users where uname = '${uname}'
</select>
测试
@GetMapping("/inject/1")@ResponseBodypublicList<User>selectOne(@RequestParam("uname")String uname){return userService.selectOne(uname);}
执行语句是
select * from users where uname = '${uname}'
,所以这里就可以直接联想到单引号闭合即可,所以用万能密码1’ or ‘1’='1进行测试
http://127.0.0.1:8080/inject/1?uname=1' or '1'='1
发现成功注入,但是如果将${}换成#{}后则会报错无法执行,原因在于:#{}相当于是进行了预编译的方式,所以就有效的避免了sql注入问题
模糊查询
这里在前篇提到过模糊查询的三种方式
select * from t_user where username like '%${mohu}%'
select * from t_user where username like "%"#{mohu}"%"
select * from t_user where username like concat('%',#{mohu},'%')
可以看到第二条中,
"%"#{mohu}"%"
预编译前后的%是独立出来的,而写成
'%#{mohu}%'
这种形式,预编译时就会将%当做字符来处理从而报错,此时若经验不足将#改成了$即:
'%${mohu}%'
,就会导致SQL注入问题
接口
StringselectTwo(@Param("uname")String uname);
配置
<select id="selectTwo" resultType="user">
select * from users where uname like '%${uname}%'
</select>
测试
这里由于换了查询方式就无法在使用万能密码获取数据,所以这里将返回类型改为了String,这样就可以通过报错信息来获取我们注入的内容
@GetMapping("/inject/2")@ResponseBodypublicStringselectTwo(@RequestParam("uname")String uname){try{return userService.selectTwo(uname);}catch(Throwable e){return e.toString();}}
http://127.0.0.1:8080/inject/2?uname=1' or updatexml(1,concat(0x7e,(select database()),0x7e),1)--+
In查询
当查询语句有in是,只需要将in后的内容进行闭合即可绕过
配置
<selectid="selectThree"resultType="user">
select * from users where uid in (${uid})
</select>
其他内容都跟模糊查询一样就不贴了
http://127.0.0.1:8080/inject/3?uid=1) or updatexml(1,concat(0x7e,(select database()),0x7e),1)--+
order by注入
和in查询原理基本相同
<selectid="selectFour"resultType="user">
select * from users order by ${uid}
</select>
http://127.0.0.1:8080/inject/4?uid=1 and(updatexml(1,concat(0x7e,(select database())),0));
综上情况来看,要避免mybatis的注入问题,其实最好的方式就是使用预编译方式
项目文件
链接:https://pan.baidu.com/s/1B3Ui-KeGL001JVgFjs9l5g?pwd=1axd
提取码:1axd
java -jar mybatis.jar 运行即可
版权归原作者 Sentiment. 所有, 如有侵权,请联系我们删除。