我是靠谱客的博主 靓丽抽屉,最近开发中收集的这篇文章主要介绍【SQL注入】Mybatis框架下的sql注入白盒审计,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

一、Mybatis框架下传递参数的两种方式

1.select * from [tablename] where [column]=#{value}

#{value},即使用JDBC预编译模式,可以有效防止sql注入漏洞的产生。

2.select * from [tablename] where [column]=${value}

${value},该方式为sql语句的动态拼接,若该参数外部可控且未做校验,则存在sql注入的风险。

二、Mybatis框架下两种提供SQL语句的方式

1.在*mapper.xml文件中书写sql语句

<select id="selectByPrimaryKey" parameterType="java.lang.Integer" resultMap="BaseResultMap">
select * from t_student where id = #{id}
</select>

这种方式需要搜索*mapper.xml的文件中是否使用了${},并向上跟踪${}里的参数,确认参数是否由外部传入且做了严格的参数校验。

2.使用SQL语句构建器类在Java代码中构建sql语句

Mybatis3中提供了一个工具类,可以简单的创建一个实例来调用方法生成SQL语句,一个简单的代码示例如下:

return new SQL() {{
SELECT("*");
FROM("t_student");
WHERE("id = #{id}");
WHERE("student_name = #{studentName}");
ORDER_BY("student_score");
}}.toString();

以上代码构建的sql语句等价于

SELECT *
FROM t_student
WHERE (id = #{id} AND student_name = #{studentName})
ORDER BY student_score

使用SQL类构建sql语句时,除了使用#{}和${}来传入可变参数外,也可以使用Java中的各种语法来传入变量,比如使用String.format()传入参数、使用"+"拼接参数等,而通过这些方式传入的参数,都不会经过预编译的处理。

因此,当项目使用SQL类构建语句时,我们可以全局搜索SQL类,检查构建sql语句的过程中是否存在${}、String.format()、"+"等动态拼接参数的情况,并跟踪这些参数是否外部可控且做了严格的校验。

三、Mybatis框架下无法使用#{}的场景

观察如下两个sql语句,order by后面的参数为变量,其中第一个sql语句使用${}拼接,第二个sql语句使用#{}进行预编译处理。当使用#{}时,mybatis会在参数两边加上单引号,导致sql语句报错。

可以简单的理解为,某个字段加上单引号会失去原本意义时,则无法使用#{},例如表名、列名、sql关键字、函数等。所以我们在黑盒测试时,如果发现这些参数由外部传入,需要特别注意是否存在sql注入问题。

select id, name, age
FROM t_student
order by id desc;
select id, name, age
FROM t_student
order by id 'desc'

四、Mybatis框架下容易存在sql注入的场景

1.order by

正如上文所说,order by后面的字段名、升序降序关键字无法预编译,因此如果这部分参数由外部传入,则可能存在sql注入的风险。

2.模糊查询like

比如想要查询名字中带zhang的学生信息,sql语句如下:

select * FROM t_student where name like '%zhang%'

如果使用#{}传入zhang,sql语句如下:

select * FROM t_student where name like '%#{key}%'

但此时sql执行会报错:

java.sql.SQLException: Parameter index out of range (1 > number of parameters, which is 0).

而部分开发为了解决该问题,直接将sql语句改为:

select * FROM t_student where name like '%${key}%'

这样虽然可行,但同时也存在sql注入的风险。

比较好的做法是将like后的语句改为concat('%',#{key},'%')

3.in

同条件多值查询时,想查询id为1、2、3的数据,如:

select * from t_student where id in (1,2,3)

如果使用#{},则实际查询的sql语句会变为:

select * FROM t_student WHERE id in ('1,2,3')

因此开发也可能为了功能的正常而使用${}来拼接参数,引入sql注入的问题。

比较好的做法是使用mybatis的foreach循环指令。

4.在使用SQL类在Java代码中构建sql语句时,对于一些不是由用户输入的数据,开发直接使用了"+"拼接在sql语句中,比如一些由系统随机生成的id值,但是该参数可从接口处传入,也可能造成sql注入风险。

虽然mybatis框架提供了强大的数据库操作的能力,但如果代码书写不规范,依然会存在sql注入的问题,对于上面提到的4中场景,不论是黑盒测试还是代码审计,都应该重点关注。

五、Mybatis框架下sql注入payload的构造

这里主要讲的是SQL类构建sql语句时payload的构造,最好的办法就是本地搭建mybatis环境,运行一下对应的代码。还是之前提到的代码:

private static String selectStudentByid() {
return new SQL() {{
SELECT("*");
FROM("t_student");
WHERE("id = ${id}");
WHERE("student_name = #{studentName}");
ORDER_BY("student_score");
}}.toString();
}

该代码生成的sql语句如下:

SELECT * FROM t_student WHERE (id = ${id} AND student_name = #{studentName}) ORDER BY student_score

可以发现,where之间会用AND连接,并且WHERE会在条件两边加上括号,那么此时可以从外部传入诸如1)#这样的参数验证是否存在sql注入。

有时候虽然某个参数外部可控且没做校验,但是通过业务逻辑,也可能避免sql注入。

最后

以上就是靓丽抽屉为你收集整理的【SQL注入】Mybatis框架下的sql注入白盒审计的全部内容,希望文章能够帮你解决【SQL注入】Mybatis框架下的sql注入白盒审计所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(60)

评论列表共有 0 条评论

立即
投稿
返回
顶部