系列篇其他文章,推荐顺序观看~
JdbcRowSetImpl利用链
前言
首先说明一下:利用链都有自己的使用场景,要根据场景进行选择不同的利用链。
JdbcRowSetImpl利用链用于fastjson反序列化漏洞中。
为什么?
因为fastjson会在反序列化类时自动调用set开头的方法(不一定是setter方法),而JdbcRowSetImpl中存在一个set开头的方法,即setAutoCommit()
,该这个方法中调用了connect()
方法,connect()
方法返回值是Connection
类,返回值是由DataSource.getConnection()产生,作用是向“数据源”发起连接(Java中的Connection接口类是用于建立与数据库之间的连接的)。而这个“数据源”是可控的。
JdbcRowSetImpl利用链分析
setAutoCommit()
方法代码如下:
可以看到,当this.conn
为null时,会调用connect()
方法,然后赋值给this.conn
。也就是说肯定会调用connect()
方法执行。
connect()
方法代码如下:
主要是下面这段代码:如果this.getDataSourceName()
有值的时候会进入
InitialContext var1 = new InitialContext();
DataSource var2 = (DataSource)var1.lookup(this.getDataSourceName());
return this.getUsername() != null && !this.getUsername().equals("") ? var2.getConnection(this.getUsername(), this.getPassword()) : var2.getConnection();
这段代码大概意思是执行InitialContext.lookup(this.getDataSourceName())
返回一个数据源对象DataSource
,然后再调用getConnection()
方法,返回一个Connection
对象。
大概理解为:向数据源DataSource
发起了获取请求。
而这个数据源DataSource
是由this.getDataSourceName()
决定的,那接下来看一看这个方法做了什么:
原来是返回this.dataSource
值,这个值从哪来呢?
通过搜索,发现是由setDataSourceName()
方法来设置,值为该方法的参数值。
接下来,看看在哪里调用了该方法:通过搜索发现并没有位置调用它。
想一下:没有地方调用,这个this.dataSource
值怎么来?又怎么完成上述的过程呢?
别急,setDataSourceName()
方法不刚好是“set”开头的嘛,所以可以利用fastjson反序列化来触发。
这样一来,整个思路就通了:
- 我们想执行恶意操作,关键是如何才能成功执行
DataSource.getConnection()
,因为该方法结合JNDI是可以远程加载资源的(JNDI注入)。 - 想执行这个操作,需要使用到
JdbcRowSetImpl
中的setAutoCommit()
和setDataSourceName()
这两个方法。 - 其中
setAutoCommit()
方法用于执行connect()
,进而执行DataSource.getConnection()
操作。 - 而
setDataSourceName()
方法是为了获取到DataSource
,使getConnection()
可以顺利执行。 setAutoCommit()
和setDataSourceName()
这两个方法,都是“set”开头的,所以fastjson在反序列化的时候,都可以自动执行。
因此fastjson反序列化漏洞是可以结合JdbcRowSetImpl来完成利用的!