ysoserial JRMP相关模块分析(一)- payloads/JRMPListener
字数 1894 2025-08-27 12:33:22

ysoserial JRMPListener模块深度分析

一、JRMPListener模块概述

JRMPListener是ysoserial工具中的一个利用模块,主要功能是通过反序列化漏洞在目标主机上开启一个JRMP Server服务。该模块的核心是利用Java反序列化机制,特别是UnicastRemoteObject类的readObject方法,来实现远程命令执行。

二、技术原理

1. 核心利用链

JRMPListener模块的利用基于以下技术原理:

  • 利用UnicastRemoteObject类的readObject方法在反序列化时会自动调用reexport方法
  • reexport方法会调用exportObject,从而开启JRMP监听服务
  • 攻击者可以通过JRMP协议与这个服务交互,实现远程命令执行

2. 关键类分析

ActivationGroupImpl

  • ActivationGroupImplUnicastRemoteObject的子类
  • 被选为主要利用类是因为它能够方便地构造出UnicastRemoteObject实例
  • 实际利用中,ActivationGroupImpl可以被替换为UnicastRemoteObject本身

UnicastRemoteObject

  • 核心类,实现了readObject方法
  • 反序列化时会自动调用reexport方法
  • reexport方法会调用exportObject,开启JRMP监听

UnicastServerRef

  • 负责实际的JRMP服务端实现
  • 包含exportObject方法,用于导出远程对象

三、利用流程详解

  1. 构造恶意序列化数据

    • 使用newConstructorForSerialization创建UnicastRemoteObject或其子类实例
    • 设置端口号为攻击者指定的值
    • 序列化该对象
  2. 发送恶意数据

    • 将序列化数据发送到目标服务器的反序列化入口点
  3. 目标服务器反序列化

    • 目标服务器反序列化数据时调用UnicastRemoteObject.readObject
    • readObject调用reexport方法
    • reexport调用exportObject开启JRMP监听
  4. 二次攻击

    • 攻击者使用JRMPClient连接新开启的JRMP服务
    • 发送实际的攻击payload执行命令

四、关键代码分析

1. 序列化对象构造

// 使用newConstructorForSerialization创建对象
Class<?> clazz = Class.forName("sun.rmi.server.UnicastServerRef");
Constructor<?> constructor = clazz.getDeclaredConstructor(ObjID.class, TCPEndpoint.class, boolean.class);
constructor.setAccessible(true);

// 构造UnicastServerRef实例
Object unicastServerRef = constructor.newInstance(
    new ObjID(ObjID.ACTIVATOR_ID), 
    new TCPEndpoint(port), 
    true
);

// 创建RemoteObject子类实例
Class<?> remoteObjectClass = Class.forName("java.rmi.server.RemoteObject");
Constructor<?> remoteObjectConstructor = remoteObjectClass.getDeclaredConstructor(RemoteRef.class);
remoteObjectConstructor.setAccessible(true);

Object remoteObject = remoteObjectConstructor.newInstance(unicastServerRef);

// 创建最终的反序列化对象
Class<?> unicastRemoteObjectClass = Class.forName("java.rmi.server.UnicastRemoteObject");
Constructor<?> unicastRemoteObjectConstructor = Serializable.class.cast(
    Reflections.getFirstCtor("sun.rmi.server.UnicastRemoteObject")
);

Object unicastRemoteObject = Reflections.newInstanceForConstructor(
    unicastRemoteObjectConstructor,
    new Class[]{RemoteRef.class},
    new Object[]{unicastServerRef}
);

2. UnicastRemoteObject.readObject关键代码

private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
    in.defaultReadObject();
    reexport();
}

private void reexport() throws RemoteException {
    if (ref != null) {
        ref.exportObject(this, null, true);
    }
}

五、技术要点总结

  1. 反序列化利用条件

    • 目标类或其父类实现了自定义的readObject方法
    • readObject方法能够执行危险操作(如开启网络服务)
  2. JRMPListener特点

    • 不依赖常见的InvocationHandlerProxy机制
    • 利用UnicastRemoteObject的内置反序列化行为
    • 需要二次攻击(先开启服务,再通过JRMP发送实际payload)
  3. 构造技巧

    • 可以使用UnicastRemoteObject或其子类(如ActivationGroupImpl
    • 父类可以选择RemoteObjectRemoteServer
    • 端口号通过UnicastServerRefTCPEndpoint设置

六、防御建议

  1. 输入验证

    • 对所有反序列化入口进行严格校验
    • 使用白名单机制限制可反序列化的类
  2. 安全配置

    • 使用Java安全管理器限制危险操作
    • 配置java.rmi.server.useCodebaseOnly=true
  3. 代码加固

    • 重写关键类的readObject方法增加安全检查
    • 使用ObjectInputFilter过滤危险类
  4. 网络防护

    • 限制不必要的JRMP端口开放
    • 监控异常的JRMP连接行为

七、扩展思考

  1. 与RMI的关系

    • RMI基于JRMP协议实现
    • 可以使用RMI Client攻击JRMPListener开启的服务
    • 但需要注意Java沙盒限制(ExecCheckingSecurityManager
  2. 反制风险

    • 攻击者可能利用JRMPListener进行反制
    • 需谨慎处理不受信任的JRMP连接
  3. 变种利用

    • 可尝试结合其他gadget链增强攻击效果
    • 探索其他readObject方法的潜在利用点

通过深入理解JRMPListener的工作原理,安全研究人员可以更好地防御此类攻击,同时也能够开发更有效的检测和防护方案。

ysoserial JRMPListener模块深度分析 一、JRMPListener模块概述 JRMPListener是ysoserial工具中的一个利用模块,主要功能是通过反序列化漏洞在目标主机上开启一个JRMP Server服务。该模块的核心是利用Java反序列化机制,特别是 UnicastRemoteObject 类的 readObject 方法,来实现远程命令执行。 二、技术原理 1. 核心利用链 JRMPListener模块的利用基于以下技术原理: 利用 UnicastRemoteObject 类的 readObject 方法在反序列化时会自动调用 reexport 方法 reexport 方法会调用 exportObject ,从而开启JRMP监听服务 攻击者可以通过JRMP协议与这个服务交互,实现远程命令执行 2. 关键类分析 ActivationGroupImpl ActivationGroupImpl 是 UnicastRemoteObject 的子类 被选为主要利用类是因为它能够方便地构造出 UnicastRemoteObject 实例 实际利用中, ActivationGroupImpl 可以被替换为 UnicastRemoteObject 本身 UnicastRemoteObject 核心类,实现了 readObject 方法 反序列化时会自动调用 reexport 方法 reexport 方法会调用 exportObject ,开启JRMP监听 UnicastServerRef 负责实际的JRMP服务端实现 包含 exportObject 方法,用于导出远程对象 三、利用流程详解 构造恶意序列化数据 : 使用 newConstructorForSerialization 创建 UnicastRemoteObject 或其子类实例 设置端口号为攻击者指定的值 序列化该对象 发送恶意数据 : 将序列化数据发送到目标服务器的反序列化入口点 目标服务器反序列化 : 目标服务器反序列化数据时调用 UnicastRemoteObject.readObject readObject 调用 reexport 方法 reexport 调用 exportObject 开启JRMP监听 二次攻击 : 攻击者使用JRMPClient连接新开启的JRMP服务 发送实际的攻击payload执行命令 四、关键代码分析 1. 序列化对象构造 2. UnicastRemoteObject.readObject关键代码 五、技术要点总结 反序列化利用条件 : 目标类或其父类实现了自定义的 readObject 方法 该 readObject 方法能够执行危险操作(如开启网络服务) JRMPListener特点 : 不依赖常见的 InvocationHandler 或 Proxy 机制 利用 UnicastRemoteObject 的内置反序列化行为 需要二次攻击(先开启服务,再通过JRMP发送实际payload) 构造技巧 : 可以使用 UnicastRemoteObject 或其子类(如 ActivationGroupImpl ) 父类可以选择 RemoteObject 或 RemoteServer 端口号通过 UnicastServerRef 的 TCPEndpoint 设置 六、防御建议 输入验证 : 对所有反序列化入口进行严格校验 使用白名单机制限制可反序列化的类 安全配置 : 使用Java安全管理器限制危险操作 配置 java.rmi.server.useCodebaseOnly=true 代码加固 : 重写关键类的 readObject 方法增加安全检查 使用 ObjectInputFilter 过滤危险类 网络防护 : 限制不必要的JRMP端口开放 监控异常的JRMP连接行为 七、扩展思考 与RMI的关系 : RMI基于JRMP协议实现 可以使用RMI Client攻击JRMPListener开启的服务 但需要注意Java沙盒限制( ExecCheckingSecurityManager ) 反制风险 : 攻击者可能利用JRMPListener进行反制 需谨慎处理不受信任的JRMP连接 变种利用 : 可尝试结合其他gadget链增强攻击效果 探索其他 readObject 方法的潜在利用点 通过深入理解JRMPListener的工作原理,安全研究人员可以更好地防御此类攻击,同时也能够开发更有效的检测和防护方案。