白盒审计-SQL注入
字数 1098 2025-08-10 09:43:36
Mybatis下的SQL注入漏洞分析与防御
一、Mybatis的两种占位符
Mybatis在XML文件中支持两种占位符号:
- #{}:预编译参数,Mybatis会将其替换为
?,然后使用PreparedStatement的参数设置方法安全地设置值 - ${}:字符串替换,Mybatis会直接将参数值替换到SQL语句中,存在SQL注入风险
二、常见SQL注入场景
1. IN语句中的SQL注入
错误用法:
Select * from news where ids in (#{ids}) <!-- 会报错 -->
Select * from news where ids in (${ids}) <!-- 有注入风险 -->
正确用法:
Select * from news where ids in
<foreach collection="ids" item="item" open="(" separator="," close=")">
#{item}
</foreach>
2. LIKE语句中的SQL注入
错误用法:
Select * from news where title like '%#{name}%' <!-- 会报错 -->
Select * from news where title like '%${name}%' <!-- 有注入风险 -->
正确用法:
Select * from news where title like concat('%', #{name}, '%')
3. ORDER BY语句中的SQL注入
错误用法:
select * from test order by #{Name} <!-- 会报错,生成错误SQL:order by 'Name' -->
select * from test order by ${Name} <!-- 有注入风险 -->
正确处理方式:
- 对传入参数进行白名单校验
- 在代码层面对参数进行转义和验证
三、漏洞审计方法
1. 代码审计步骤
- 在项目中全局搜索
${查找所有使用字符串替换的地方 - 逆向追踪参数传递路径:
- 从Mapper XML文件开始
- 追踪到DAO层接口
- 追踪到Service层实现
- 追踪到Controller层
- 检查参数是否经过过滤或校验
2. 以tmall项目为例的审计过程
- 在
ProductMapper.xml文件中发现${orderUtil}使用 - 通过Free Mybatis plugin插件跳转到DAO层代码
- 追踪到
ProductServiceImpl.java中的getList方法 - 继续追踪到
ProductController.java中的调用位置 - 发现
OrderUtil类从请求参数直接获取orderBy和isDesc值,未做任何过滤
3. 漏洞验证方法
- 构造异常输入测试:
orderyBy=1返回正常orderyBy=99报错(可能暴露数据库结构)
- 使用sqlmap进行自动化测试:
python sqlmap.py -r 1.txt
四、防御措施
- 优先使用#{}:在大多数情况下都应使用
#{}预编译参数 - 必须使用${}时的防护:
- 对参数进行严格的白名单校验
- 对参数进行转义处理
- 避免直接使用用户输入
- 特定场景处理:
- IN语句使用
<foreach>标签 - LIKE语句使用
concat函数 - ORDER BY进行参数校验
- IN语句使用
- 代码审计:
- 定期检查项目中的
${}使用情况 - 对关键参数进行安全测试
- 定期检查项目中的
五、总结
Mybatis框架下SQL注入的主要原因是开发者为解决语法问题而错误地使用${}代替#{}。安全开发的关键在于:
- 理解两种占位符的区别
- 掌握常见场景的正确写法
- 对必须使用
${}的情况实施严格的安全控制 - 建立代码审计机制,及时发现潜在风险
通过规范的编码实践和安全意识,可以有效避免Mybatis环境下的SQL注入漏洞。