跨越语言的艺术:Weblogic序列化漏洞与IIOP协议(1)

    String bind_name = String.valueOf(System.currentTimeMillis()); 
    context.rebind(bind_name, foreignOpaqueReference);  // 绑定远程对象 rebind\_any
    context.lookup(bind_name);  // 获取远程对象 resove\_any
    ClusterMasterRemote clusterMasterRemote = (ClusterMasterRemote)context.lookup(bind_name);
    System.out.println(clusterMasterRemote.getServerLocation("whoami"));
}

}


### 3.1 Java 中的攻击流程


![在这里插入图片描述](https://img-blog.csdnimg.cn/2c147464f794407d8e64d55631e4e131.png#pic_center)


1、在 Weblogic 的 IIOP 序列化交互开始时,客户端初始化上下文信息 `new InitialContext()` ,通过 `locateNameService()` 方法将目标地址、序列化对象等信息封装到IIOP协议的请求包中作为 `LocateRequest` 消息与Weblogic服务端建立通信。


![在这里插入图片描述](https://img-blog.csdnimg.cn/94544d4a4f45435a9e8bcb792ea249c5.png#pic_center)


2、当客户端收到服务端的`LocateReply`消息后表示通信交互已建立,客户端会解析响应消息体中的信息,并将其中的相关信息(如 Key Address ,内部类地址、上下文等信息)解析作为下次请求的消息体验证信息。  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/7d7840afd1584f4081188215dd4579c8.png#pic_center)


3、通信建立后, IIOP 会将建立交互时服务端响应包中的 `Key Address` 作为下次请求中的 `Key Address`,执行 `bind()` 或 `rebind()` 方法时,绑定对象名称、对象的序列化数据等信息会封装到请求消息体中的 `Stub data` 字段中作为消息传输。


![在这里插入图片描述](https://img-blog.csdnimg.cn/b38924c640da4f5a97fe3f99e3e52c43.png#pic_center)  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/336213f441f24859a1bf995ad06d361c.png#pic_center)


4、 IIOP 协议执行`lookup()`方法时,首先通过创建的上下文对象调用其中的`lookup()`方法,`lookup()`方法根据上下文中是否为`NamingContextAny`类型来决定调用的`lookup()`方法,由于上下文对象属于`NamingContextAny`类型,因此通过`Utils.stringToWNameComponent(var1) 方`法将字符串 var1 转换成 `WNameComponent(Wide Name Component)`数组,并将其传递给 `this.lookup()` 方法,最后通过调用`resolve_any()`方法将消息封装成序列化字节流发送给服务端。


## 0x04 IIOP 跨语言实现


在《 IIOP 攻击流程》章节的交互部分中,当 weblogic 在内网环境下,客户端会将 `LocateReply` 中返回的 weblogic 内部类的内网地址作为下次发包的目标地址,因此会出现客户端向自己的内部地址发包,出现网络通信中断问题。同时,由于 Go 语言中并没有官方的 IIOP 协议库可用,我们在 Goby 安全工具上实现漏洞攻击是比较困难的。如果外挂 java 程序的话会使Goby越来越臃肿,这并不符合白帽汇安全研究院的漏洞价值观。我们认为漏洞是一门艺术,漏洞检测和利用的方式应该以最优雅的形式出现。针对上面的问题,我们索性直接复刻 IIOP 协议作为最终的通用解决方案。


### 4.1 实现思路


**协议通信的本质是字节流的形式在网络中传输数据。因此, Go 实现 IIOP 协议的方式就是模拟 IIOP 通信的字节流。**


对于上文中的攻击流程,我们将攻击过程中 IIOP 协议通信分为建立交互、绑定远程对象、获取远程对象,执行对象方法四个部分。对应在 Java 主要通过一下方法完成:



Context context = new InitialContext(env); // 初始化上下文,建立交互连接 LocateRequest消息 LocateReply消息
context.rebind(bind_name, foreignOpaqueReference); // 绑定远程对象 Request消息 rebind_any方法
context.lookup(bind_name); // 绑定远程对象 Request消息 lookup方法
context.lookup(bind_name).getServerLocation(“whoami”); // 执行远程对象中的方法


我们在 IIOP 协议模拟实现时仅需要实现上述方法在执行过程中协议交互的字节流即可。


### 4.2 GIOP 协议规范


GIOP(General Inter-ORB Protocol)是一种 CORBA 规范定义的协议,用于在分布式对象之间进行通信和交互,定义了对象请求、响应、异常、命名等基本的通信模式和协议规范。


![在这里插入图片描述](https://img-blog.csdnimg.cn/847030e1c8e34b31aa4bbd528636af5c.png#pic_center)


GIOP 消息由消息头和消息体两部分组成。


在 GIOP 消息头中包括了 Magic (GIOP标识)、Version(GIOP版本)、Message Flags(标志位)、Message type(消息类型)、Message size(消息体长度)四个字段;


在GIOP消息体中,主要包含了Request id(请求标识)、TargetAddress(请求目标对象键 ID )、Key Address(Key 地址)、Reqest operation(操作方法)、SerivceContext(服务上下文信息)等字段。


由于篇幅有限,这里并不过多叙述 GIOP 字段的含义,如想深入研究协议内容,请参考我们总结的手册《[GIOP-Protocol-Analysis]( )》。


#### 4.2.1 GIOP 协议通信流程


1、在通信的初始阶段,首先客户端向服务端发送 `LocateRequest` 类型的消息与服务端建立通信,服务端验证请求信息并响应`LocateReply` 类型的消息表示收到了客户端的请求信息,开始与客户端进行交互通信。


2、通信建立完成后,客户端发送一个 `Request` 类型的消息来执行服务端中的方法,`Request` 消息的请求体中包含了key地址(`Key Address`)、执行方法名称(`Request operation`)、消息上下文(`Service Context`)和调用远程对象信息(`Stub data`)等内容。


3、服务端接收并正常解析请求报文后,回应一个 `Reply` 类型的 `No Exception` 消息。如果请求报文在服务端中解析出错/异常,则回应一个 `Reply` 类型的`User Exception` / `System Exception` 消息,同时响应体中会附带异常ID(`Exception id`)信息。


### 4.3 初始化上下文



Context context = new InitialContext(env); // 初始化上下文,建立交互连接 LocateRequest消息 LocateReply消息


在 Java 代码中,初始化上下文信息在创建对象的过程中建立IIOP协议的交互流程。因此,在 Go 语言中实现`new InitialContext(env)`创建对象时生成的字节流并发送给Weblogic即可。`new InitialContext(env)`对象的创建过程在IIOP协议具体实现中为`LocateRequest`消息。


![在这里插入图片描述](https://img-blog.csdnimg.cn/66cb5c96cbc949379e7be62a88110c8b.png#pic_center)


客户端发送的 `LocateRequest` 消息是一个固定的格式。其中包含了 GIOP 协议标识,协议版本,消息类型、消息标识等信息。


![在这里插入图片描述](https://img-blog.csdnimg.cn/3b3b249f61b545129d35e4cc9e325262.png#pic_center)


由于 `LocateRequest` 是一个固定格式的序列,所以可以直接将该序列发送给服务端,开始建立交互连接。


![在这里插入图片描述](https://img-blog.csdnimg.cn/8918c7eb6cfe41afad4877dc5fecd593.png#pic_center)


服务端在收到 `LocateRequest` 消息并验证正确后,会向客户端响应一个 `LocateReply` 消息。 响应的 `LocateReply` 消息包含了有关服务器的上下文信息、key地址、长度等信息。


![在这里插入图片描述](https://img-blog.csdnimg.cn/34b507fb09134260af3dae0b25ad9ca0.png#pic_center)


在交互建立完成后,下次请求通信过程中会用到响应体中的 key 地址,需要将key地址解析出来,以便于下次请求包中使用。因此,需要先将`Key Address length` 的长度提取出来,再根据 Key 的长度计算出`Key Address`,并将 key 地址存储起来,以便下次请求使用。同时,因为我们下次发包的目标地址是自主可控的,这就从根源上避免了上面出现的NET网络问题。这样,通信就已经正常建立了。  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/60ce7f3425f64d5a8e26fa7ad148e7da.png#pic_center)


在通信建立之后,为了验证服务端返回的 `Key Address` 的有效性,我们向服务端发送了一个方法名为 `_non_existent` 的 `Request` 请求消息。如果服务端返回的状态为 `No Exception`,则说明该 `Key Addresss` 是有效的。


### 4.4 绑定远程对象



context.rebind(bind_name, foreignOpaqueReference); // 绑定远程对象 Request消息 rebind_any方法


在 Java 语言中,使用 `rebind()` 方法可以将一个对象绑定到 Weblogic 注册中心上。在 Go 语言中,我们可以实现 `context.rebind()` 方法的字节流,将要绑定的名称和序列化对象添加到字节流中,然后发送给 Weblogic。


在 IIOP 协议的具体实现中,`rebind()` 方法的操作方法名为 `rebind_any`。  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/5e3a1d3ce01b4b5894d8bac7058e4d6a.png#pic_center)


通过 `rebind_any` 方法,将 `Stub data` 中的绑定名称以及序列化对象等数据发送给服务端,服务端执行重绑定操作,将对象绑定到Weblogic Register上。


![在这里插入图片描述](https://img-blog.csdnimg.cn/42d56f8b2f534901a881e5800ba1bf75.png#pic_center)


Go 模拟 `rebind_any` 方法的核心将生成的 payload 字节流增加到请求体的尾部 `Stub data` 部分。


### 4.5 获取远程对象



context.lookup(bind_name); // 绑定远程对象 Request消息 lookup方法


在 Java 代码中,通过上下文对象中的 `lookup()` 方法可以获取 Weblogic 中绑定名称的存根对象。同样,在 Go 语言中,我们可以实现 `context.rebind()` 方法的字节流,并将要绑定的名称添加到该字节流中,然后将其发送给 Weblogic。


在 IIOP 协议的具体实现中,`lookup()` 方法的操作方法名为 `resolve_any`。


![在这里插入图片描述](https://img-blog.csdnimg.cn/41efba5a68f34f7c870f234484a37f10.png#pic_center)


`resolve_any` 方法通过发送注册命名信息获取注册中心上的存根对象。这里的 Go 字节码实现和上面的相似,都是将信息放到 `Stub data` 中发送给服务端,只不过这里存放的是存根的命名信息。


![在这里插入图片描述](https://img-blog.csdnimg.cn/8deb95649ee84c53b49e8e53911814ca.png#pic_center)


`resolve_any` 的响应消息会生成一个新的 `Key Address`,该key包含获取远程对象的引用地址等信息,在执行这个对象中的方法时,要将新请求消息中的 `Key Address` 替换成该信息。这样就可以正常执行该对象中的方法了。


### 4.6 执行对象方法



context.lookup(bind_name).getServerLocation(“whoami”); // 获取远程对象,执行对象中的getServerLocation方法进行回显


执行 `lookup` 方法后,我们获取到了远程对象的存根信息,这时就可以调用对象中的方法来实现远程方法调用的目的。


![在这里插入图片描述](https://img-blog.csdnimg.cn/0371bb404c8b4c36b4decb967df6a3c4.png#pic_center)


例如,我们在 CVE-2023-21839 漏洞上绑定了回显类并有名为 `getServerLocation()`的回显方法。在 Go 语言中,我们只需要按照 GIOP 字节流的格式实现字节流,并将字段 `Request operation` 的值设置为我们要执行的方法名,`Operation length` 设置为方法名的长度,`Stub data` 中设置为执行方法的字节流,最后封装成 GIOP 字节流发送给 Weblogic 即可。具体的的漏洞回显效果,正如下图所示:


![在这里插入图片描述](https://img-blog.csdnimg.cn/16cc6a15f1034d4290ec002e7baac6ee.gif#pic_center)


## 0x05 总结


在白帽汇安全研究院,漏洞检测和利用是一项创造性的工作,我们致力于以最简洁,高效的方式来实现。为了在 Goby 中实现 Weblogic 序列化漏洞的最佳效果和利用方式,我们花费大量精力阅读 IIOP 序列化源码、分析协议流量、调试协议中的字段和字节码。最终,我们成功在 Go 语言中实现了 IIOP 协议漏洞利用框架。为了验证框架的可靠性,我们以 Weblogic 反序列化漏洞(CVE-2023-21839)为例,在 Goby 上实现了完美的漏洞攻击效果,并加入了一键回显、一键反弹 shell 的利用方式。


**本文中演示的漏洞与功能将于 4 月 18 号(下周二)在Goby上线,届时请关注 Goby 版本更新通知或微信社群公告。**


**Goby社区版免费下载体验:https://gobysec.net/**


## 0x06 参考


[ChatGPT (openai.com)]( )


[Java CORBA (seebug.org)]( )


[RMI-IIOP Programmer’s Guide (oracle.com)]( )


[Tutorial: Getting Started Using RMI-IIOP (oracle.com)]( )


**自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。**

**深知大多数网络安全工程师,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!**

**因此收集整理了一份《2024年网络安全全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。**
![img](https://img-blog.csdnimg.cn/img_convert/9f98bfa242067eb21555cac306a11fec.png)
![img](https://img-blog.csdnimg.cn/img_convert/d676f3569222826ac5e99f10a55991f8.png)
![img](https://img-blog.csdnimg.cn/img_convert/c2b1d52b607c242c21d888a4b9a6580c.png)
![img](https://img-blog.csdnimg.cn/img_convert/fe4313f24c1a16928cd9d53d35eb460e.png)
![img](https://img-blog.csdnimg.cn/img_convert/d69d49531037cd608234e0c1f3aeaaac.png)
![img](https://img-blog.csdnimg.cn/img_convert/3ae5669a074fb81e490f9954e265a9ab.png)

**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上网络安全知识点,真正体系化!**

**由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新**

**如果你觉得这些内容对你有帮助,可以添加VX:vip204888 (备注网络安全获取)**
![img](https://img-blog.csdnimg.cn/img_convert/48ebd2b5117ea47ed602168b780f6549.png)



### 一、网安学习成长路线图


网安所有方向的技术点做的整理,形成各个领域的知识点汇总,它的用处就在于,你可以按照上面的知识点去找对应的学习资源,保证自己学得较为全面。  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/aa7be04dc8684d7ea43acc0151aebbf1.png)


### 二、网安视频合集


观看零基础学习视频,看视频学习是最快捷也是最有效果的方式,跟着视频中老师的思路,从基础到深入,还是很容易入门的。  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/f0aeee2eec7a48f4ad7d083932cb095d.png)


### 三、精品网安学习书籍


当我学到一定基础,有自己的理解能力的时候,会去阅读一些前辈整理的书籍或者手写的笔记资料,这些笔记详细记载了他们对一些技术点的理解,这些理解是比较独到,可以学到不一样的思路。  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/078ea1d4cda342f496f9276a4cda5fcf.png)


### 四、网络安全源码合集+工具包


光学理论是没用的,要学会跟着一起敲,要动手实操,才能将自己的所学运用到实际当中去,这时候可以搞点实战案例来学习。  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/e54c0bac8f3049928b488dc1e5080fc5.png)


### 五、网络安全面试题


最后就是大家最关心的网络安全面试题板块  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/15c1192cad414044b4dd41f3df44433d.png)![在这里插入图片描述](https://img-blog.csdnimg.cn/b07abbfab1fd4edc800d7db3eabb956e.png)  



**一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**
![img](https://img-blog.csdnimg.cn/img_convert/049e575c98d49f48fa627e6d4b2b38b7.png)

s://img-blog.csdnimg.cn/15c1192cad414044b4dd41f3df44433d.png)![在这里插入图片描述](https://img-blog.csdnimg.cn/b07abbfab1fd4edc800d7db3eabb956e.png)  



**一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**
[外链图片转存中...(img-rxse3NU4-1712927486325)]

  • 5
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值