栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Mybatis框架下的sql注入白盒审计

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

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 * from t_student where id = #{id}

这种方式需要搜索*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注入。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/774670.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号