MyBatis 框架下 SQL 注入审计分析

前言

SQL 注入漏洞是 Web 安全中最常见的问题之一。在 Java 中,由于预编译技术和各种 ORM 框架的普及,SQL 注入问题虽然有所减少,但仍然存在隐患。对于新手代码审计者而言,面对 Java Web 应用中多个框架的复杂组合,往往无从下手。本文以 MyBatis 框架中使用不当导致的 SQL 注入问题为例,希望能为新手提供一些启发。


一、MyBatis 的 SQL 注入问题

MyBatis 的 SQL 语句可以通过注解写在类的方法上,也可以通过 XML 文件编写。SQL 语句需要手动编写或使用代码生成工具(如 MyBatis Generator)生成。MyBatis 支持两种参数占位符:#$,分别表示预编译字符串拼接。例如:

1
2
3
<select id="queryAll" resultMap="resultMap">
SELECT * FROM NEWS WHERE ID = #{id}
</select>

其中,# 使用预编译,而 $ 则直接拼接 SQL。

在 MyBatis 框架下,易导致 SQL 注入的常见场景包括以下三种:

  1. 模糊查询

    示例代码:

    1
    SELECT * FROM news WHERE title LIKE '%#{title}%'

    使用 # 会导致程序报错,新手程序员可能会将 # 替换为 $。如果在 Java 层面未对用户输入进行有效处理,就可能产生 SQL 注入漏洞。

    正确写法

    1
    SELECT * FROM news WHERE title LIKE CONCAT('%', #{title}, '%')
  2. IN 之后的多个参数

    示例代码:

    1
    SELECT * FROM news WHERE id IN (#{ids})

    使用 # 处理多个参数会报错,正确做法是使用 <foreach> 来遍历参数,而不是简单替换为 $

    正确写法

    1
    2
    3
    4
    SELECT * FROM news WHERE id IN 
    <foreach collection="ids" item="item" open="(" separator="," close=")">
    #{item}
    </foreach>
  3. ORDER BY 动态排序

    在这种场景下,建议在 Java 层设置字段或表名的白名单数组,允许用户仅传入合法的索引值,从而避免 SQL 注入。

    特别需要注意的是,MyBatis Generator 自动生成的 SQL 中,ORDER BY 默认使用 $,容易引发注入问题。


二、实战思路

通过分析一个开源 CMS 项目,介绍如何定位和确认 SQL 注入漏洞。

  1. 导入项目

    在 IDEA 首页选择 Get from Version Control,输入项目地址 https://gitee.com/mingSoft/MCMS.git,下载完成后等待 Maven 加载依赖。

  2. 搜索 $ 关键字

    • 使用 Ctrl+Shift+F 搜索 XML 文件中的 $,筛选出可能存在注入风险的代码。
    • IContentDao.xml 文件为例,找到多处 $ 拼接的 SQL 语句,对这些语句逐一进行分析。
  3. 确定映射关系

    • 根据 MyBatis 的 select id,定位对应的映射对象、实现类和控制层代码。
    • getSearchCount 为例,反推调用链找到前台接收的参数,并确认是否存在输入过滤。
  4. 漏洞确认

    • 启动项目,构造恶意 SQL 请求,验证是否存在注入漏洞。
    • 例如,访问以下 URL:
      1
      http://localhost:8080/ms-mcms/mcms/search.do?categoryId=1') or updatexml(1,concat(0x7e,(SELECT @@version),0x7e),1)#
      如果返回数据库版本号 5.7.27,则可以确认漏洞存在。

三、总结

以上是 MyBatis SQL 注入审计的基本方法。对于新手,可以尝试分析不同的注入点,熟悉常见的注入场景和防范措施。以下是几个关键点:

  1. 重点关注三个高危场景LIKE 查询、IN 多参数、ORDER BY 动态排序。
  2. 排查 XML 文件中的$:筛选出可能存在注入风险的语句并逐一分析,特别是 MyBatis Generator 自动生成的代码。
  3. 参数检查:在 Java 层面严格验证用户输入,假定所有输入均为恶意,提前防范潜在攻击。
  4. 注解 SQL 的审计:方法与 XML 类似,但需要额外关注注解中的动态拼接内容。

通过以上方法,可以有效识别和防范 MyBatis 框架下的 SQL 注入问题。