Skip to content

Latest commit

 

History

History
65 lines (54 loc) · 4.85 KB

File metadata and controls

65 lines (54 loc) · 4.85 KB

C3p0DataSource JDBC URL Attack(C3p0DataSource3)

  • 类别:javanative 别名:— 优先级:—
  • 作者:Unam4、Springkill
  • 依赖c3p0com.mchange.v2.c3p0.debug.CloseLoggingComboPooledDataSource

作用

构造一个 CloseLoggingComboPooledDataSource(c3p0 的 ComboPooledDataSource 子类),预置好任意 jdbcUrl。当上游 gadget 通过 getter(getConnection)触发它时,c3p0 会用这个 JDBC URL 去建立连接,从而把「调用一个 getter」转化为「攻击者可控的 JDBC URL 利用」(如 H2 jdbc 执行 JS 表达式)。它是 DataSource 系与 JdbcUrl 系之间的桥接构件。

链接标签

  • 入口 tags
    • DataSourceChains —— 标识本 gadget 属于「DataSource 触发链」一族,可被 DataSource 触发框架接纳。
    • Getter —— 本 gadget 通过一个 getter 方法(getConnection)被触发,需由上游「暴露/调用危险 getter」的 gadget 承接。
    • Serializable —— 产物可被 Java 原生序列化承载。
  • 衔接 nextTagsJdbcUrlChains —— 之后需接一个「消费 JDBC URL」的 gadget(如 H2/HSQLDB 等 JDBC 利用构件),由后者产出真正被 setJdbcUrl 装入的恶意 URL 字符串。
  • excludes:无。

源码剖析

public class C3p0DataSource3 implements Gadget {
    private final String getterMethodName = "getConnection";
    private final String getterPropertyName = "connection";

    public Object getObject(String jdbcUrl) {
        CloseLoggingComboPooledDataSource dataSource = new CloseLoggingComboPooledDataSource();
        dataSource.setJdbcUrl(jdbcUrl);
        return dataSource;
    }

    @Override
    public Object invoke(GadgetContext context, GadgetChain chain) throws Exception {
        String jdbcUrl = (String)chain.doCreate(context);
        context.put(ContextTag.SUPER_CLASS_NAME_KEY, DataSource.class);
        context.put(ContextTag.SPECIAL_METHOD_NAME_KEY, "getConnection");
        context.put(ContextTag.GETTER_PARAM_NAME_KEY, "connection");
        return this.getObject(jdbcUrl);
    }
}

逐段解释:

  • invokechain.doCreate(context) 取内层对象——按「由内向外」的构建约定,内层此时应是下游 JdbcUrlChains gadget 产出的一个恶意 JDBC URL 字符串,故这里直接强转 (String)
  • 随后向 GadgetContext 注入三个键,用来告知上游(触发方)该如何在反序列化时命中本对象:
    • SUPER_CLASS_NAME_KEY = DataSource.class:本对象需以 javax.sql.DataSource 类型被识别/持有。
    • SPECIAL_METHOD_NAME_KEY = "getConnection":触发本链的方法名,即上游需要调用 getConnection()
    • GETTER_PARAM_NAME_KEY = "connection":对应的属性名(getter 去掉 get 前缀),供 BeanComparator 等按属性名触发 getter 的上游 gadget 使用(如 CommonsBeanutils 系)。
  • getObject(jdbcUrl) 真正构造数据源:new CloseLoggingComboPooledDataSource()setJdbcUrl(jdbcUrl)。该类是 c3p0 调试包下的 ComboPooledDataSource 变体,序列化后当其 getConnection() 被调用即会用 jdbcUrl 发起连接。
  • 反编译头部 Could not load ... CloseLoggingComboPooledDataSource 属正常(缺 c3p0 依赖不影响逻辑分析)。

C3p0DataSource4 唯一区别是所用的 ComboPooledDataSource 子类不同(本类用 CloseLoggingComboPooledDataSource),逻辑完全一致,属互为备选以适配不同白名单/可加载性。

参数(@Param)

本类无 @ParamjdbcUrl 来自下游 gadget(nextTags=JdbcUrlChains)的产物,getterMethodName/getterPropertyName 为私有常量固定为 getConnection/connection

适用版本与原理要点

  • 适用于目标存在 c3p0 依赖、且能加载 com.mchange.v2.c3p0.debug.CloseLoggingComboPooledDataSource 的环境。
  • 核心原理:ComboPooledDataSource.getConnection() 会依据可控 jdbcUrl 建连,从而把「任意 getter 调用」升级为「任意 JDBC URL 利用」,常配 H2 JDBC 执行 JS/字节码达成 RCE。
  • 本构件只负责「DataSource → JdbcUrl」的桥接,真正的 RCE 依赖下游 JDBC 构件(如 H2JavaJdbc1)与上游 getter 触发器(如 CommonsBeanutils 系或 Fastjson)配合。

所属预设链

自由构件,未直接出现在 51 条预设链中(usedInChains 为空)。可参考同类的 Fastjson C3p0 Jdbc h2 链思路手工组合。

关联

  • 上游(承接 Getter/getConnection):CommonsBeanutils1、Fastjson 系等能触发 getter 的 gadget。
  • 下游(nextTags=JdbcUrlChains):H2JavaJdbc1H2JavaExecJdbc1 等 JDBC URL 利用构件。
  • 同族:C3p0DataSource4(仅数据源子类不同)、C3p0_C3p0Jndi / C3p0_C3p0Jndi2(走 JNDI 而非 JDBC URL)。