漏洞挖掘:一次反序列化漏洞学习
0x01 漏洞背景
该漏洞是继 CVE-2015-4852、CVE-2016-0638、CVE-2016-3510 之后的又一个重量级反序列化漏洞。 该漏洞使用了在当时为新型技术的 rmi 反序列化漏洞绕过了之前的修补补丁 。适用版本包括了 10.3.6.0、12.1.3.0、12.2.1.0 以及 12.2.1.1 等多个版本。笔者将从环境搭建、漏洞补丁分析、绕过方法思考、payload 构建等多个方面进行研究,尽可能的将一些坑点和知识点摸排清楚,从 0 到 1 学习 weblogic 反序列化。
0x02 环境搭建及补丁安装
2021最新整理网络安全/渗透测试/安全学习/100份src技术文档(全套视频、大厂面经、精品手册、必备工具包、路线)一>点我<一
0x1 环境搭建
现成环境
可以采用现成的 docker 环境,执行以下命令生成对应版本的 dockerdocker run -d -p 7001:7001 -p 8453:8453 turkeys/weblogic:10.3.6
自动搭建
利用 Docker 自动化搭建,在 github 下载搭建代码[https://github.com/BabyTeam1024/WeblogicAutoBuild.git](https://github.com/BabyTeam1024/WeblogicAutoBuild.git)
本次实验环境采用 jdk7u21 和 weblogic 10.3.6.0,在 jdk_use 和 weblogic_use 文件夹下存放相对应版本的程序
执行如下命令:
0x2 补丁安装
本次使用的补丁是 p23094342_1036_Generic.zip
获取到补丁后用如下指令进行安装
补丁信息如下
0x03 补丁分析及绕过
0x1 补丁分析
第一时间拿到补丁后,使用之前的 CVE-2016-3510 payload 打了下没有反应,并且从 log 中发现如下报错
从报错中清楚的了解到 MarshalledObject 是不可被反序列化的。反过头来看下补丁是如何修补的。头脑简单的笔者一开始认为这次又是添加了什么白名单,就在各种 blacklist 中疯狂寻找,无果,郁闷了半天。突然在使用 idea 分析时在补丁包中发现了一个 MarshalledObject.class 文件,如下所示
笔者为了证明是这个相同包路径的接口影响了 MarshalledObject 反序列化,做了以下操作
然后再使用 CVE-2016-3510 payload 试了下,发现可以成功
那么总结下这次补丁是编写相同包名和类名的接口覆盖之前的类,使其变得不可反序列化,妙啊!
0x2 前置知识-RMI 反序列化
理论上讲找个类替代 MarshalledObject 的功能即可完成绕过,但这次并没有这么做,而是引出了一种比较有意思的反序列化漏洞,RMI 反序列化漏洞(关于这个系列的漏洞,笔者打算单独开个板块进行分析)。这次主要介绍如何绕过该补丁。
RMI 为 Java 远程方法调用,是 Java 编程语言里,一种用于实现远程过程调用的应用程序编程接口。它使客户机上运行的程序可以调用远程服务器上的对象。RMI 反序列整个体系比较复杂,但一般掌握了其中几个知识点就可以应对很多场景了。笔者在整理 RMI 知识的时候,总结了 RMI 通信过程中可利用的反序列化点
大致分为三类客户端触发,服务端触发和**注册中心触发,**ysoserial 中涉及的几个反序列化点都在对应的地方标注了。
客户端触发
1.当客户端向注册中心发送 lookup 数据包时注册中心会把 stub 对象返回给客户端并在客户端触发 readObject2.当客户端使用 StreamRemoteCall 与远程通信时,在 executeCall 函数中存在反序列化在客户端触发 readObject(payloads/JRMPClient 配合 exploit/JRMPListener)3.当客户端使用 DGCImpl_Stub 与 DGC 服务端交互式时会在 dirty 函数中反序列化远程传递过来的 Lease 对象序列化后的数据,在客户端触发 readObject
服务端触发
1.当客户端向服务端发送调用远程方法的请求时会先使用 DGCImpl_Stub 和服务端通信,在处理 dirty 请求时会在对象申请和引用的时候在服务端触发 readObject(exploit/JRMPClient,可配合 payloads/JRMPListener)
注册中心触发
1.当客户端向注册中心发送 lookup 数据包时会把 binding 中 stub 对应的 String 类型名字以序列化的形式发送,注册中心收到数据包后,将会在注册端触发 readObject,反序列化传过来的名字。2.当服务端或客户端向注册中心(RegistryImpl)bind 绑定 stub 的时候会在注册端触发 readObject(exploit/RMIRegistryExploit)3.当服务端或客户端向注册中心(RegistryImpl)unbind 解绑 stub 的时候会在注册端触发 readObject4.当服务端或客户端向注册中心(RegistryImpl)rebind 重新绑定 stub 的时候会在注册端触发 readObject
0x3 RMI 反序列化原理
CVE-2017-3248 可采用客户端或是服务端触发两种方式绕过上次漏洞补丁。重点分析 payloads/JRMPClient 配合 exploit/JRMPListener 完成此次攻击利用的深层次原理。
payloads/JRMPClient 的反序列化背景是客户端获取到来自 RegistryImpl_Skel 的回应后,将会调用 DGCClient 的与远程 DGCServer 进行通信。调用栈如下
主要问题出现在 StreamRemoteCall.class 类的 executeCall 函数上
观察发现 this.in 为 ConnectionInputStream 类型并没有黑名单的限制,因此只要服务端可控,就可以像客户端发送任意反序列化数据。
碰巧的是在 RemoteObjectInvocationHandler 的反序列化代码里会调用这个 StreamRemoteCall 类里的 executeCall 方法
结合之前的调用栈 dgc.dirty 函数就已经可以触发到 executeCall 代码
0x04 利用方法
0x1 如何构造 Payload
前面分析了漏洞原理,那么客户端需要构建怎样的代码才能触发到反序列化呢?这个还要从 rmi 机制说起,详细内容可以将会在之后的 rmi 专题进行讲解,这里只是把大概逻辑捋一捋,这一节会有很多类和变量,不理解没关系主要了解过程。
首先思考一个问题,RMI 客户端如何调用远程服务器上的其他类?RMI 机制是这么做的,涉及到对端调用的类将会生成类似 Stub 和 Skel 的对等结构,其中 Stub 在客户端保存(客户端可自己生成比如 RegistryImpl_stub,也可通过网络通过网络从服务端获取 Proxy(MyclassImpl))。因为我们只分析客户端,这里引出一张客户端 RMI 调用流程图
黄线:客户端首先调用 getRegistry 函数生成注册中心 Stub(RegistryImpl_stub)
黄线:接着通过 lookup 方法与远程服务通信,远程服务会在 ObjectTable 中匹配该 stub 包含的 Target,进行路由分发
紫线:服务端接收到 lookup 请求后,会将已经生成好的**代理类 Proxy(MyclassImpl)**返回给客户端
绿线:客户端收到代理类 Stub,直接调用其中的方法就会与远程服务通信并在远程执行相关代码
我们重点关注下紫线部分的处理流程,服务端到底返回的是个什么东西,我们找到服务端启动代码
当代码执行到 13 行时,因为 UserImpl 继承了 UnicastRemoteObject 类并且在构造方法里调用了父类构造方法,所以将会执行 UnicastRemoteObject 类中的构造方法
构造方法会调用 exportObject
下面重点来了,如何封装传递给 Client 端的 Stub
方便理解笔者倒着分析,在最后利用 RemoteObjectInvocationHandler 代理了我们需要执行的类,那么 RemoteRef 是如何而来的,从当前代码中只能看见时 getClientRef 获取到的
getClientRef 代码如下,this.ref 是什么时候赋值的?
在 UnicastRemoteObject 构造方法一开始时就赋值了,sref 如何生成
sref 其实是 UnicastServerRef 是 UnicastRef 的子类
在其构造方法中创建了 LiveRef 对象并赋值给了 UnicastRef 的 ref 变量
可能会有些绕,整体可以总结为如下代码
仿照服务端的 createProxy 函数,将 RemoteObjectInvocationHandler 封装进代理类。
利用代码如下所示,完整项目代码在https://github.com/BabyTeam1024/CVE-2017-3248
0x2 整合利用
整个过程使用 JRMP Server 端反打 Client 端 Step 1 使用 JRMPListener 监听端口
**Step 2 发送漏洞 payload **反序列化数据中包含 rmi 客户端链接代码
0x05 总结
CVE-2017-3248 使用了 RMI 反序列化漏洞,也揭开了笔者分析 RMI 漏洞原理的新篇章。后面将不断分析 Weblogic 相关反序列化漏洞,以及系统总结整理 RMI 反序列化漏洞的基础知识和简单利用。
评论