记一次“SQL注入” Bypass
字数 1274 2025-08-06 20:12:44

MyBatis OGNL 表达式注入漏洞分析与Bypass技术

1. 漏洞背景

MyBatis 是一个优秀的持久层框架,它默认支持 OGNL (Object-Graph Navigation Language) 表达式。在特定情况下,这种支持可能导致从 SQL 注入转化为远程代码执行(RCE)的风险,同时还能绕过一些已有的安全机制。

2. OGNL 表达式基础

OGNL 是一种强大的表达式语言,允许:

  • 访问对象属性
  • 调用方法
  • 进行表达式计算
  • 创建对象实例

在 MyBatis 中,OGNL 主要用于动态 SQL 的构建,如 <if><choose> 等标签中的条件判断。

3. 漏洞原理

3.1 注入点分析

当用户输入直接拼接到 MyBatis 的 OGNL 表达式中且未经过滤时,攻击者可以构造恶意 OGNL 表达式实现注入。

常见危险场景:

<select id="findUser" parameterType="String" resultType="User">
    SELECT * FROM users WHERE id = ${id}
</select>

${id} 直接拼接 SQL 语句,而非使用预编译的 #{id}

3.2 从 SQLi 到 RCE 的转化

当攻击者能够控制 OGNL 表达式时,可以利用 OGNL 的特性执行任意代码:

@org.apache.commons.io.IOUtils@toString(@java.lang.Runtime@getRuntime().exec('whoami').getInputStream())

4. 漏洞利用

4.1 基本利用方式

  1. 识别使用 ${} 的 MyBatis 查询
  2. 构造恶意 OGNL 表达式
  3. 通过表达式执行系统命令

4.2 实际攻击示例

假设存在以下 MyBatis 映射:

<select id="getUser" parameterType="String" resultType="User">
    SELECT * FROM users WHERE username = '${username}'
</select>

攻击者可构造 payload:

username' + (${@java.lang.Runtime@getRuntime().exec('calc')}) + '

5. Bypass 技术

5.1 绕过常规防御

  1. 黑名单过滤绕过

    • 使用反射调用方法
    • 使用字符串拼接
    • 使用十六进制或 Unicode 编码
  2. 上下文感知绕过

    • 在字符串上下文中闭合引号
    • 在数字上下文中利用类型转换

5.2 特殊场景利用

  1. order by 注入

    order by ${sortField} ${sortOrder}
    

    即使 sortOrder 被限制为 ASC/DESC,sortField 仍可能被利用

  2. like 子句注入

    <select id="search" parameterType="String" resultType="User">
        SELECT * FROM users WHERE username LIKE '%${keyword}%'
    </select>
    

6. 防御措施

6.1 开发层面

  1. 优先使用 #{} 而非 ${}

  2. 必须使用 ${} 时,严格过滤输入:

    • 白名单验证
    • 禁用危险字符和关键字
  3. 使用 MyBatis 的安全插件:

    <plugins>
        <plugin interceptor="org.mybatis.example.SafeSqlInterceptor"/>
    </plugins>
    

6.2 架构层面

  1. 最小权限原则:数据库账户只授予必要权限
  2. 启用预编译语句
  3. 使用 ORM 框架的安全特性

6.3 运行时防护

  1. 安全产品拦截危险 OGNL 表达式
  2. 监控异常数据库查询

7. 漏洞检测

7.1 代码审计要点

  1. 检查所有使用 ${} 的地方
  2. 关注动态 SQL 中的用户输入
  3. 检查 order by、group by、like 等子句

7.2 自动化检测

可使用以下工具:

  • SQLMap(支持 MyBatis 注入检测)
  • 自定义脚本检查 XML 映射文件
  • SAST 工具扫描代码

8. 总结

MyBatis 的 OGNL 表达式支持在提供灵活性的同时带来了安全风险。开发者应当:

  1. 充分了解 #{}${} 的区别
  2. 避免用户输入直接进入 OGNL 上下文
  3. 实施多层防御措施
  4. 定期进行安全审计

通过正确的使用方式和安全编码实践,可以充分利用 MyBatis 的强大功能而不牺牲安全性。

MyBatis OGNL 表达式注入漏洞分析与Bypass技术 1. 漏洞背景 MyBatis 是一个优秀的持久层框架,它默认支持 OGNL (Object-Graph Navigation Language) 表达式。在特定情况下,这种支持可能导致从 SQL 注入转化为远程代码执行(RCE)的风险,同时还能绕过一些已有的安全机制。 2. OGNL 表达式基础 OGNL 是一种强大的表达式语言,允许: 访问对象属性 调用方法 进行表达式计算 创建对象实例 在 MyBatis 中,OGNL 主要用于动态 SQL 的构建,如 <if> 、 <choose> 等标签中的条件判断。 3. 漏洞原理 3.1 注入点分析 当用户输入直接拼接到 MyBatis 的 OGNL 表达式中且未经过滤时,攻击者可以构造恶意 OGNL 表达式实现注入。 常见危险场景: ${id} 直接拼接 SQL 语句,而非使用预编译的 #{id} 。 3.2 从 SQLi 到 RCE 的转化 当攻击者能够控制 OGNL 表达式时,可以利用 OGNL 的特性执行任意代码: 4. 漏洞利用 4.1 基本利用方式 识别使用 ${} 的 MyBatis 查询 构造恶意 OGNL 表达式 通过表达式执行系统命令 4.2 实际攻击示例 假设存在以下 MyBatis 映射: 攻击者可构造 payload: 5. Bypass 技术 5.1 绕过常规防御 黑名单过滤绕过 : 使用反射调用方法 使用字符串拼接 使用十六进制或 Unicode 编码 上下文感知绕过 : 在字符串上下文中闭合引号 在数字上下文中利用类型转换 5.2 特殊场景利用 order by 注入 : 即使 sortOrder 被限制为 ASC/DESC,sortField 仍可能被利用 like 子句注入 : 6. 防御措施 6.1 开发层面 优先使用 #{} 而非 ${} 必须使用 ${} 时,严格过滤输入: 白名单验证 禁用危险字符和关键字 使用 MyBatis 的安全插件: 6.2 架构层面 最小权限原则:数据库账户只授予必要权限 启用预编译语句 使用 ORM 框架的安全特性 6.3 运行时防护 安全产品拦截危险 OGNL 表达式 监控异常数据库查询 7. 漏洞检测 7.1 代码审计要点 检查所有使用 ${} 的地方 关注动态 SQL 中的用户输入 检查 order by、group by、like 等子句 7.2 自动化检测 可使用以下工具: SQLMap(支持 MyBatis 注入检测) 自定义脚本检查 XML 映射文件 SAST 工具扫描代码 8. 总结 MyBatis 的 OGNL 表达式支持在提供灵活性的同时带来了安全风险。开发者应当: 充分了解 #{} 和 ${} 的区别 避免用户输入直接进入 OGNL 上下文 实施多层防御措施 定期进行安全审计 通过正确的使用方式和安全编码实践,可以充分利用 MyBatis 的强大功能而不牺牲安全性。