0x00 XML簡介
XML可擴展標記語言,被設計用來傳輸和存儲數據。其形式多樣
例如:
1.文檔格式(OOXML,ODF,PDF,RSS,DOCX...)
2.圖片格式(SVG,EXIF Headers,...)
3.配置文件(自定義名字,一般是.xml)
4.網絡協議(WebDAV,CalDAV,XMLRPC,SOAP,REST,XMPP,SAML,XACML,...)
某些在XML中被設計出來的特性,比如 XML schemas(遵循XML Schemas 規范)和documents type definitions(DTDs)都是安全問題來源。縱然被公開的討論了上十年,還是有一大批一大批的軟件死在針對XML的攻擊上。
其實XML實體機制很好理解,可以直接用“轉義”來理解:%和&foo從原始意義上來說是一樣的,只是後者是由我們自己來定義任意內容。
拿DTD來說,DTD中能聲明實體來定義變量(或是文字類的宏),以便在接下來的DTD或者XML文檔中使用。一般實體在DTD中定義,用來訪問內部資源,獲取裡面的文字並用來替換自己的xml文檔,而外部實體用來訪問外部資源(也就是說,這些資源能來自本地計算機,也可以是遠程主機)。在解析外部實體的過程中,XML的分析器可能會使用眾多網絡協議和服務(DNS,FTP,HTTP,SMB等等)這取決於URLs裡面被指定成什麼。外部實體用來處理那些實時更新的文檔是很有用的,然而,攻擊也能在解析外部實體的過程中發生。攻擊手段包括:
讀取本地文件(可能包含敏感信息 /etc/shadow)
內存侵犯
任意代碼執行
拒絕服務
本文將對長期以來出現的xml攻擊方法進行一個總結。
0x01 初識XML外部實體攻擊
基於外部實體的文件包含
最早被提出的XML攻擊方法是利用外部實體的引用功能來實現任意文件讀取
]> Joe &file; ...
然而這種讀取是有限制的,因為xml的解析器要求被引用的數據是完整的,我們使用一個例子來解釋什麼是完整。
]> &first;&second;
如上的xml文檔當發送給服務器時,實際上是會產生一個錯誤的 其中雖然在組合在一起時是能夠完美閉合的,但是這些實體由於在第3,4行就被解析一次,此時由於不是完美閉合的,就會拋出一個錯誤。
這種錯誤讓xml攻擊一度變得雞肋起來,因為實際上很多文件都是“未閉合形式”的,比如在php文件推薦的寫法中就是只有前面一個"
更糟糕的是,當你選擇包含的是一個完整的xml文件(比如數據庫連接文件)的時候,返回結果將是
可以看到,在標簽中的數據庫配置文檔被嵌入時,大部分內容都是省略號,只顯示了文檔的結構。這是由xml parser特性決定的。
URL Invocation
XML攻擊中有一塊常常被忽視,那就是利用URL機制以及他們的一些奇怪的特性來擴大攻擊面。
雖然XML規范並沒有要求支持任何特定的URL機制,但許多平台的底層網絡庫卻支持了幾乎所有URL機制。
借助URLs,攻擊者可以讓運行著XMLparser的主機向第三方主機發起惡意請求.
比如“server-side request forgery”(ssrf).理論上來說,URL Invocation甚至可以用來發起內部網絡中的洪水攻擊。
大部分人不知道的是,即使外部實體被禁用了,許多xml parsers還是會去解析那些URL。舉個例子,一些parsers會在文檔定義階段對url發起請求
這不是實體攻擊!
除了外部實體和基於DOCTYPE的SSRF攻擊之外,XML Schema提供了兩個在實例文檔中使用的特殊屬性,用於指出模式文檔的位置。這兩個屬性是:xsi:schemaLocation和xsi:noNamespaceSchemaLocation,前者用於聲明了目標名稱空間的模式文檔,後者用於沒有目標名稱空間的模式文檔,它們通常在實例文檔中使用。
在這個案例中,所有帶有secondaryns:前綴的都會遵循在xmlns:secondaryns中定義的機制。由於DOCTYPE定義不能出現在文檔的中部,所以當我們只對文檔某個部分可控的時候,就能利用schema_Location(http://location/of/remote/schema/primary.xsd)發起ssrf。(前提是一些設置需要設置為on,然而我們並沒有對每個xml parser進行充分的測試來研究不同環境下有什麼要求能讓我們進行ssrf攻擊,所以這也是一個待研究的方向,有興趣的wooyuner可以交流~)
0x02 引入參數實體後的攻擊手段
當我們的惡意xml被成功解析,這時我們有可能面臨兩個問題:
一,數據未閉合導致嵌入失敗(比如只存在
二,服務器進行限制導致數據不能返回。
引入參數實體之後,這兩個問題就能得到解決。
參數實體以%開頭 我們使用參數實體只需要遵循兩條原則:
參數實體只能在DTD聲明中使用。 參數實體中不能再引用參數實體。
CDATA轉義的妙用
CDATA部件;在CDATA部件的所有內容都會被XML解析器忽略,即CDATA部件裡面的內容緊緊這是一個字符串文本的作用。一個 CDATA 部件以""標記結束。那麼我們能不能構造一個這樣的頁面來返回那些文件呢
%dtd; ]> &all;
combine.dtd如下
前面也提到過,當xml parsers會把xml的參數實體% start % end馬上解釋,由於沒有閉合 就會拋出錯誤,那麼這裡的%start為何能正常地解析呢? 這是因為參數實體的引用不需要在xml文檔解析的時候保持xml閉合,這樣就繞過了限制。
通過這樣我們就能讀取所有數據了(base64編碼也可)
外帶數據bypass回顯限制
另一種使用參數實體的手段就是外帶數據了。
利用參數實體,我們能夠把需要讀取的文件通過一些協議(http ftp等)發送到我們的服務器上,那麼通過日志查看就能獲取數據了 我們可以這麼構造
%dtd;]> &send;
然後在我們可控的http://example.com/
放置如下DTD
%all;
流程如下
Win10最新版官方下載/Win10安裝圖文教程
XXE的奇門遁甲
基於XInclude的文件包含
XInclude提供了一種較為方便的取回數據的思路(再也不用擔心數據不完整而導致parser拋出一個錯誤)而我們能夠通過parse屬性,強制引用文件的類型。
不過Xinclude需要手動開啟,測試發現所有xml parser都默認關閉這一特性。
拒絕服務
XXE攻擊也能用來發起拒絕服務攻擊
如下的遞歸引用,從下至上以指數形式增多
]> &lol9;
回憶一下解析過程,當XML處理器載入這個文檔的時候,它會包含根元素,而裡面定義了實體&lol9 ,而19實體擴展成了包含了“&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;”這個字符串。
如此遞歸上去,壓入內存的東西呈指數增長,實驗發現,一個小於1KB的XML攻擊payload能消耗3GB的內存。
特定環境下的攻擊和限制
Java&Xerces
默認的Oracle's Java Runtime Environment下的XML parser是Xerces,一個apache的項目。而Xerces和Java提供了一系列的特性,這些特性又能導致一些嚴重的安全問題。上述的那些攻擊手法(DOCTYPEs for SSRF,文件讀取,參數實體的外帶數據)在java的默認配置下能夠運用自如,java/Xerces也支持XInclude 但是需要setXIncludeAware(true) 和setNamespaceAware(true)。
java規范能夠支持如下的URL機制
http
https
ftp
file
jar
令人吃驚的是Java的file協議能夠用來列目錄,比如說,在linux下面“file:///”會列出/目錄下所有東西:
bin
boot
dev
etc
home
...
jar協議jar:http://host/application.jar!/file/within/the/zip會導致服務器首先取得文件然後解壓這個以jar開頭!結尾的包 並提取後面的文件。從攻擊者的角度看,完全能夠定制一些高壓縮比的包(比如1000:1)這些ZIP炸彈能用來攻擊反病毒系統,或者用來消耗目標機的硬盤/內存資源。注意,jar URLs能在任何接受DOCTYPE定義的JAVA Xerces系統上使用。所以,即使外部實體關閉了,還是能夠進行攻擊。
php&expect的RCE
很遺憾,這個擴展並不是默認安裝的,然而安裝了這個擴展的XXE漏洞,是能夠執行任意命令。
]>
&cmd;
那麼就會返回如下
uid=501(Apple) gid=20(staff) groups=20(staff),501(access_bpf),12(everyone),61(localaccounts),79(_appserverusr),80(admin),81(_appserveradm),
98(_lp