- 类别:javanative 别名:— 优先级:—
- 作者:Unam4、Springkill
- 依赖:
c3p0(com.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 原生序列化承载。
- 衔接
nextTags:JdbcUrlChains—— 之后需接一个「消费 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);
}
}逐段解释:
invoke先chain.doCreate(context)取内层对象——按「由内向外」的构建约定,内层此时应是下游JdbcUrlChainsgadget 产出的一个恶意 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;jdbcUrl 来自下游 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):H2JavaJdbc1、H2JavaExecJdbc1等 JDBC URL 利用构件。 - 同族:C3p0DataSource4(仅数据源子类不同)、C3p0_C3p0Jndi / C3p0_C3p0Jndi2(走 JNDI 而非 JDBC URL)。