白盒审计-SQL注入
字数 1098 2025-08-10 09:43:36

Mybatis下的SQL注入漏洞分析与防御

一、Mybatis的两种占位符

Mybatis在XML文件中支持两种占位符号:

  1. #{}:预编译参数,Mybatis会将其替换为?,然后使用PreparedStatement的参数设置方法安全地设置值
  2. ${}:字符串替换,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. 代码审计步骤

  1. 在项目中全局搜索 ${ 查找所有使用字符串替换的地方
  2. 逆向追踪参数传递路径:
    • 从Mapper XML文件开始
    • 追踪到DAO层接口
    • 追踪到Service层实现
    • 追踪到Controller层
  3. 检查参数是否经过过滤或校验

2. 以tmall项目为例的审计过程

  1. ProductMapper.xml文件中发现${orderUtil}使用
  2. 通过Free Mybatis plugin插件跳转到DAO层代码
  3. 追踪到ProductServiceImpl.java中的getList方法
  4. 继续追踪到ProductController.java中的调用位置
  5. 发现OrderUtil类从请求参数直接获取orderByisDesc值,未做任何过滤

3. 漏洞验证方法

  1. 构造异常输入测试:
    • orderyBy=1 返回正常
    • orderyBy=99 报错(可能暴露数据库结构)
  2. 使用sqlmap进行自动化测试:
    python sqlmap.py -r 1.txt
    

四、防御措施

  1. 优先使用#{}:在大多数情况下都应使用#{}预编译参数
  2. 必须使用${}时的防护
    • 对参数进行严格的白名单校验
    • 对参数进行转义处理
    • 避免直接使用用户输入
  3. 特定场景处理
    • IN语句使用<foreach>标签
    • LIKE语句使用concat函数
    • ORDER BY进行参数校验
  4. 代码审计
    • 定期检查项目中的${}使用情况
    • 对关键参数进行安全测试

五、总结

Mybatis框架下SQL注入的主要原因是开发者为解决语法问题而错误地使用${}代替#{}。安全开发的关键在于:

  1. 理解两种占位符的区别
  2. 掌握常见场景的正确写法
  3. 对必须使用${}的情况实施严格的安全控制
  4. 建立代码审计机制,及时发现潜在风险

通过规范的编码实践和安全意识,可以有效避免Mybatis环境下的SQL注入漏洞。

Mybatis下的SQL注入漏洞分析与防御 一、Mybatis的两种占位符 Mybatis在XML文件中支持两种占位符号: #{} :预编译参数,Mybatis会将其替换为 ? ,然后使用PreparedStatement的参数设置方法安全地设置值 ${} :字符串替换,Mybatis会直接将参数值替换到SQL语句中,存在SQL注入风险 二、常见SQL注入场景 1. IN语句中的SQL注入 错误用法 : 正确用法 : 2. LIKE语句中的SQL注入 错误用法 : 正确用法 : 3. ORDER BY语句中的SQL注入 错误用法 : 正确处理方式 : 对传入参数进行白名单校验 在代码层面对参数进行转义和验证 三、漏洞审计方法 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进行自动化测试: 四、防御措施 优先使用#{} :在大多数情况下都应使用 #{} 预编译参数 必须使用${}时的防护 : 对参数进行严格的白名单校验 对参数进行转义处理 避免直接使用用户输入 特定场景处理 : IN语句使用 <foreach> 标签 LIKE语句使用 concat 函数 ORDER BY进行参数校验 代码审计 : 定期检查项目中的 ${} 使用情况 对关键参数进行安全测试 五、总结 Mybatis框架下SQL注入的主要原因是开发者为解决语法问题而错误地使用 ${} 代替 #{} 。安全开发的关键在于: 理解两种占位符的区别 掌握常见场景的正确写法 对必须使用 ${} 的情况实施严格的安全控制 建立代码审计机制,及时发现潜在风险 通过规范的编码实践和安全意识,可以有效避免Mybatis环境下的SQL注入漏洞。