从反射链的构造看Java反序列漏洞

2017-10-23 429417人围观 ,发现 8 个不明物体 WEB安全漏洞

* 本文作者:朱杰,本文属FreeBuf原创奖励计划,未经许可禁止转载

概况

今天我想从构造反射链的从无到有到被利用来谈谈java的反序列化漏洞,从反射的最开始到执行payload,一个从无到有的过程,首先我们介绍一下Transformer类。

Transformer类介绍

打开org.apache.commons.collections.Transformer类,可以看到源码中对该类的解释是从一个对象变为另一个对象,如下图所示:

image.png

从上图我们可以看到,里面有一个transform方法,通过描述我们理解为执行转变的方法,下面用一个简单的例子,解释一下这个类的作用,如下图所示:

image.png

当输入Runtime.class时,transform方法中输出了类的类型,如上图中红线处所示,当我需要转变对象时,相应的操作应该在transform方法当中。

我们查找有哪些类使用了Transformer接口,有如下几个类分别是ConstantTransformer,invokerTransformer,ChainedTransformerTransformedMap。

下面我们利用以上的三个类一边构造出反序列漏洞的payload一边看他们的运作原理。

ConstantTransformer

通过查看源码,我们看到该类使用了Transformer的接口,重写了transformer的方法,如下图所示:

image.png

image.png

上面两幅图,可以看出transform返回的是iConstant的变量,iConstant的变量必定在ConstantTransformer(Object)方法中被赋值。

下面举个例子详细看使用,根据上图中的代码,如下图所示:

image.png

此时根据源码,我需要查看返回的iConstant对象类型,在源码中设置断点,开启debug运行,运行结果如下图:

image.png

上图中可以看到,内部构造出Runtime的对象类型。

InvokerTransformer

打开invokerTransformer查看源码的解释,可知是通过反射创建一个新的对象实例,如下图所示:

image.png

看到也使用了Transformer的接口,查看其transform方和和构造方法如下图所示:

image.png

上图中所示,构造函数会将iMethodName和iParamType的值传递进来,在transform方法中通过反射的方法,得到了这个方法的对象,最后返回的是Method对象。

使用举例,根据上述源码构造一个对象,并且调用transform对象,如下图所示:

image.png

在源码中设置断点,开启debug模式,进行分析,如下图所示:

image.png

参数传递进来,继续跟踪到transform函数当中,如下图所示:

image.png

继续跟踪查看method变量的值如下图所示:

image.png

image.png

这里解释一下下图中三行代码的意思:

image.png

cls变量获取到的是传递进来的input的对象值,此处input传递的是Runtime的对象,下面两行代码要反射Runtime的getRuntime方法,iMethodName表示要得到的方法名称,iParamTypes表示方法中所使用的参数类型的数组。

此处的iMethodName需要Mehtod对象,因此此处是getMethod,因此iParamTypes对应的是getMethod对象的参数类型集合,getMethod方法文档如下图所示:

image.png

通过查阅官方文档,我们知道了参数应该是String.class和Class[].class

继续往下执行invoke方法,因为是反射getRuntime()方法,参数为空,所以iArgs的值可以为空,回到主程序代码可以发现为null,如下图所示:

image.png

执行完毕之后,输出如下图所示:

image.png

成功的反射出了Runtime.getRuntime()的方法,然而如果要执行任意代码的化,还需要有exec代码段,全部应该是Runtime.getRuntime().exec(“calc.exe”)。

构造payload

此时我们已经获得了GetRuntime()的Method对象,如果要执行exec(“calc.exe”),我们还需要进行一次invoke反射的过程,因此我们根据上面构造出下面的代码段,如下图:

image.png

上图中,构造出tran2的方法,配置invoke的参数都为null,利用tran2.transform(run),反射invoke方法,过程与上文中一样,此处直接看输出了:

image.png

此处已经是Runtime类了,继续构造exec(“calc.exe”)代码段,如下图所示:

image.png

重复上面的步骤,运行代码如下图所示:

image.png

成功弹窗,以上是构造反射链的过程,那么如何去让反射链执行呢,我们来看一下ChainedTransformer这个类,我觉得从名称上已经很能说明问题了,反射链,我们细细看一下这个类。

ChainedTransformer

看一下这个类的源码解释,如下图所示:

image.png

没有很特别的地方,是Commons Collections中的类,继续往下看:

image.png

这里很有意思啊,和上文中的InvokerTransformer如出一辙,利用for循环,对传入的transformers[i]运行transform方法,这里无非就是把我们上文的步骤利用一个for循环整合在了一起,现在我构造一个以数组为主的反射链进行弹窗,代码段如下图所示:

image.png

构造出了chain方法之后,还需要调用transform方法,至于传入的对象会被很快覆盖掉,所以input的类型可以任意。

执行如下图所示:

image.png

执行成功。

如何才能不通过调用transform方法执行反射链呢?

下面就要去寻找类了,寻找到调用了ChainedTransformer类中的transform方法的类,这个类叫TransformedMap,从名称来看就非常的相似,找到他的setValue方法,如下图所示:

image.png

看到了吗,只要我们控制valueTransformer的值为ChainTransformer对象就可以执行反射链了,找到他的赋值地点,如下图所示:

image.png

image.png

从以上两幅图可以看出,valueTransformer变量是可控的,只要在decorate方法中赋值即可,我们给出下面的代码段:

image.png

利用decorate为valueTransformer赋值,然后在最后一行触发了setValue方法,其他的都是为了满足这两个条件形成,执行截图如下:

image.png

总结

从以上分析我们可以得出,java反序列化漏洞,只要反射链构造合适,我们可以执行任意的java代码。

* 本文作者:朱杰,本文属FreeBuf原创奖励计划,未经许可禁止转载

发表评论

已有 8 条评论

取消
Loading...
css.php