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

概况

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

Transformer**类介绍**

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

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

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

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

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

ConstantTransformer

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

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

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

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

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

InvokerTransformer

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

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

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

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

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

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

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

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

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

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

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

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

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

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

构造payload

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

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

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

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

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

ChainedTransformer

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

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

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

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

执行如下图所示:

执行成功。

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

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

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

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

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

总结

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

原文发布于微信公众号 - FreeBuf(freebuf)

原文发表时间:2017-10-23

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏小古哥的博客园

JavaScript闭包的深入理解

闭包算是javascript中一个比较难理解的概念,想要深入理解闭包的原理,首先需要搞清楚其他几个概念: 一、栈内存和堆内存 学过C/C++的同学可能知道,计算...

3937
来自专栏Dato

SQL 中的日期和时间类型

在我们SQL中一般支持三种数据类型。 date:日历日期,包括年(四位),月和日。 time: 一天中的时间,包括小时,分和秒。可以用变量time(p)来表示秒...

3356
来自专栏丑胖侠

《Drools7.0.0.Final规则引擎教程》第4章 Function函数

Function函数 首先来看一下function函数的语法结构图: ? 函数是将语义代码放置在规则文件中的一种方式,就相当于java类中的方法一样。函数...

2238
来自专栏本立2道生

python中的编码与解码

编码/解码本质上是一种映射(对应关系),比如‘a’用ascii编码则是65,计算机中存储的就是00110101,但是显示的时候不能显示00110101,还是要显...

1331
来自专栏转载gongluck的CSDN博客

c++ 中__declspec 的用法

c++ 中__declspec 的用法 语法说明: __declspec ( extended-decl-modifier-seq ) 扩展修饰符: ...

9387
来自专栏V站

PHP反序列化深入理解

在PHP中右serialize()和unserialize()两个函数,php里面的值都可以使用函数serialize()来返回一个包含字节流的字符串来表示。u...

2145
来自专栏积累沉淀

JDK动态代理的底层实现原理

JDK动态代理的底层实现原理      动态代理是许多框架底层实现的基础,比如Spirng的AOP等,其实弄清楚了动态代理的实现原理,它就没那么神奇了,下面就来...

5927
来自专栏java一日一条

java面试小题系列(一)

973
来自专栏九彩拼盘的叨叨叨

ES6 之 Proxy 介绍

Proxy(代理) 是 ES6 中新增的一个特性。Proxy 让我们能够以简洁易懂的方式控制外部对对象的访问。其功能非常类似于设计模式中的代理模式。

1073
来自专栏林德熙的博客

dotnet 设计规范 · 结构体定义

易变的属性指的是在调用属性返回值的时候返回的是新的实例,易变的属性会有很多的问题。

791

扫码关注云+社区

领取腾讯云代金券