Mybatis框架下易产生SQL注入漏洞的场景和修复方法

一、Mybatis框架下易产生SQL注入漏洞的场景

在基于Mybatis框架的Java白盒代码审计工作中,通常将着手点定位在Mybatis的配置文件中。通过查看这些与数据库交互的配置文件来确定SQL语句中是否存在拼接情况,进而确立跟踪点。

通过总结,Mybatis框架下易产生SQL注入漏洞的情况有以下三种:

1. 模糊查询 like

以新闻详情页面为例,按照新闻标题对新闻进行模糊查询,如果考虑安全编码规范问题,其对应的SQL语句如下:

select * from `news` where `title` like ‘%#{title}%‘

但这样写是不对的,于是研发人员将SQL语句修改为:

select * from `news` where `title` like ‘%${title}%‘

这种情况程序不再报错,但是此时产生了SQL语句拼接问题,容易产生SQL注入漏洞。

2. 多值查询 in

对新闻进行同条件多值查询的时候,用户输入 1001,1002,1003 时,如果考虑安全编码规范,对应的SQL语句为:

select * from `news` where `id` in (#{id})

这样的SQL语句虽然能执行但得不到预期结果,于是研发人员将SQL语句修改为:

select * from `news` where `id` in (${id})

修改SQL语句之后达到了预期效果,但却引入了SQL语句拼接的问题。

3. order by 之后

根据时间、点击量等进行排序时,如果考虑安全编码规范问题,SQL语句为:

select * from `news` where `title`=‘iphone‘ order by #{time} asc

由于 time 不是查询参数无法使用预编译,SQL语句虽然执行了但得不到预期结果,于是研发人员将SQL语句修改为:

select * from `news` where `title`=‘iphone‘ order by ${time} asc

修改之后虽然成功得到预期结果,但产生了SQL语句拼接问题,极有可能引发SQL注入漏洞。

二、修复方法

1. 模糊查询 like

按照标题进行模糊查询,可将SQL语句设计如下:

select * from `news` where `tile` like concat(‘%‘, #{title}, ‘%‘)

采用预编译避免了SQL语句拼接的问题,从根源上防止SQL注入漏洞。

2. 多值查询 in

对新闻进行多值查询时,可使用Mybatis自带的循环指令解决SQL语句动态拼接的问题:

select * from `news` where `id` in <foreach collection="ids" item="item" open="(" separator="," close=")">#{item}</foreach>

3. order by 之后

预编译机制只能处理查询参数,其他地方还需要研发人员根据具体情况来解决。例如 order by 排序查询:

select * from `news` where `title`=‘iphone‘ order by #{time} asc

这里 time 不是查询参数,无法使用预编译机制,只能拼接SQL语句:

select * from `news` where `title`=‘iphone‘ order by ${time} asc

这种情况下研发人员可以在java层面做映射来解决。例如:当排序字段为时间(time)或点击量(click)时,我们可以限制用户只能输入 1 或 2。

当输入 1 时,我们在代码层用 switch 语句将其映射为 time,当输入 2 时,将其映射为 click。输入其他内容时将其转换为默认排序字段 time。这样就能避免SQL注入漏洞。

参考链接

https://mp.weixin.qq.com/s?src=3&timestamp=1591321089&ver=1&signature=aort5C46VjBc1nw781Wc8WUSE8n3ErlNwWwH94BBZVSJ--3bdFc5yDWx2qD0Bs-ydAPLNqAcH01Jkncw28TLJxymWKhZAnRucnkLZHRkiQZAA89cHB0QJBKJt2TE5JCD2nrrP5MHKAtrHbMg49zhxzLGtAJhktLtQsruVERIJa0=