XXE從入門到放棄
XXE從入門到放棄
一、認識XML和XXE
XXE全稱XML External Entity Injection,也就是XML外部實體注入攻擊,是對非安全的外部實體資料進行處理時引發的安全問題。要想搞懂XXE,肯定要先了解XML語法規則和外部實體的定義及呼叫形式。
XML基礎知識
XML用於標記電子檔案使其具有結構性的標記語言,可以用來標記資料、定義資料型別,是一種允許使用者對自己的標記語言進行定義的源語言。XML文件結構包括XML宣告、DTD文件型別定義(可選)、文件元素。
XML語法規則如下:
1. 所有的XML元素都必須有一個關閉標籤
2. XML標籤對大小寫敏感
3. XML必須正確巢狀
4. XML屬性值必須加引號””
5. 實體引用 (在標籤屬性,以及對應的位置值可能會出現<>符號,但是這些符號在對應的XML中都是有特殊含義的,這時候我們必須使用對應html的實體對應的表示,比如<傅好對應的實體就是lt,>符號對應的實體就是gt)
6. 在XML中,空格會被保留 (案例如:<p>a空格B</p>,這時候a和B之間的空格就會被保留)
XML元素介紹
XML元素是指從(且包括)開始標籤直到(且包括)結束標籤的部分。
每個元素又有可以有對應的屬性。XML屬性必須加引號。
注意:
(1) XML文件必須有一個根元素
(2) XML元素都必須有一個關閉標籤
(3) XML標籤對大小寫敏感
(4) XML元素必須被正確的巢狀
(5) XML屬性值必須加引號
XML DTD介紹
DTD文件型別定義,約束了xml文件的結構。擁有正確語法的XML被稱為“形式良好”的XML,透過DTD驗證約束XML是“合法”的XML。
DTD是什麼?
XML 文件有自己的一個格式規範,這個格式規範是由一個叫做 DTD文件型別定義(document type definition) 的東西控制的。
DTD用來描述xml文件的結構,一個DTD文件包含:
元素的定義規則;元素之間的關係規則;屬性的定義規則。
DTD 可被成行地宣告於 XML 文件中,也可作為一個外部引用。
他就是長得下面這個樣子:
內部的 DOCTYPE 宣告
內部宣告DTD型別
內部宣告DTD型別宣告:<!DOCTYPE 根元素[子 元素宣告]>
引用外部實體:
我們主要關注XML外部實體的定義和呼叫方式:
<!ENTITY 實體名稱 SYSTEM "URI">
DTD資料型別
PCDA他的意思是被解析的字元資料/
PCDA他的意思是被解析的字元資料,PCDATA是會被解析器解析的文字
CDA他的意思是字元資料
CDATA是不會被解析器解析的文字,在這些文字中的標籤不會被當作標記來對待,其中的實體也不會被展開。
DTD實體介紹
(實體定義)
實體是用於定義引用普通文字或者特殊字元的快捷方式的變數
在DTD中的實體型別,一般分為:內部實體和外部實體,細分又分為一般實體和引數實體。除外部引數實體引用以字元(%)開始外,其它實體都以字元(&)開始,以字元(;)結束。
內部實體:
<!ENTITY 實體名稱 "實體的值">
外部實體:
<!ENTITY 實體名稱 SYSTEM "URI/URL">
外部引數實體:
<!ENTITY % 實體名 "實體內容”>
XML注入產生的原理
XXE漏洞全稱XML External Entity Injection即xml外部實體注入漏洞,XXE漏洞發生在應用程式解析XML輸入時,沒有禁止外部實體的載入,導致可載入惡意外部檔案,造成檔案讀取、命令執行、內網埠掃描、攻擊內網網站、發起dos攻擊等危害。xxe漏洞觸發的點往往是可以上傳xml檔案的位置,沒有對上傳的xml檔案進行過濾,導致可上傳惡意xml檔案。
xxe漏洞觸發的點往往是可以上傳XML檔案約位置,沒有對上傳的XML檔案進行過濾,導致可以上傳惡意的XML檔案。
怎麼判斷網站是否存在XXE漏洞
最直接的方法就是用burp抓包,然後,修改HTTP請求方法,修改Content-Type頭部欄位等等,檢視返回包的響應,看看應用程式是否解析了傳送的內容,一旦解析了,那麼有可能XXE攻擊漏洞,接下來,來看一個小小的展示:
這個是測試xxe的測試點:http://169.254.4.52/bWAPP/xxe-1.php
我們點選下面的Any bugs然後用burp抓包
我們隨便輸入下
從上面我們可以看到,web應用正在解析xml的內容,接受使用者特定或者自定義的輸入,然後呈現給使用者。為了驗證,我們可以構造如下的輸入:
可以看到應用程式確實是直接解析了xml,那麼如果xml文件中有一個引數是用來呼叫遠端伺服器的內容?這個引數是可控的,我們可以做什麼?
XXE漏洞-檔案讀取
PHP中測試POC
File:///path/to/file.ext
http://url/file.ext
PHP://filter/read=convert.base64-encode/resource=/home/bee/test.php
讀取文件
有回顯的xxe利用
Payload:
讀取php檔案
直接讀取php檔案會報錯,因為php檔案裡面有<>//等特殊字元,xml解析時候會當成xml語法來解析。這時候就分不清處哪個是真正的xml語句了,
直接利用file協議讀取PHP檔案,就會產生報錯。那麼需要base64編碼來讀取,
Payload:
進行解密後得到對應內容
本地測試無回顯注入讀取檔案
但是,在實際情況中,大多數情況下伺服器上的 XML 並不是輸出用的,所以就少了輸出這一環節,這樣的話,即使漏洞存在,我們的payload的也被解析了,但是由於沒有輸出,我們也不知道解析得到的內容是什麼,因此我們想要現實中利用這個漏洞就必須找到一個不依靠其回顯的方法——外帶資料
先看一下漏洞示例:
相較於前面有回顯的漏洞程式碼,我們去掉了內容輸出的一部分。這樣,用之前的payload就沒有作用了:
Payload的構造:
有了前面使用外部DTD檔案來拼接內部DTD的引數實體的經驗,我們可以知道,透過外部DTD的方式可以將內部引數實體的內容與外部DTD宣告的實體的內容拼接起來,那麼我們就可以有這樣的設想:
(1) 客戶端傳送payload 1給web伺服器
(2) web伺服器向vps獲取惡意DTD,並執行檔案讀取payload2
(3) web伺服器帶著回顯結果訪問VPS上特定的FTP或者HTTP
(4) 透過VPS獲得回顯(nc監聽埠)
首先,我們使用ncat監聽一個埠:
也可以用python建立一個建議的http服務。
python -m SimpleHTTPServer 埠
然後,我們構造payload:
我們選擇使用外部DTD,在我們自己所能掌控(或是自己搭建)的主機上編寫一個dtd檔案:
我們注意到,第一個引數實體的宣告中使用到了php的base64編碼,這樣是為了儘量避免由於檔案內容的特殊性,產生xml解析器錯誤。
Payload如下:
如圖,我們先宣告一個外部的DTD引用,然後再xml文件內容中引用外部DTD中的一般實體。
開始攻擊:
然後檢視我們的埠監聽情況,會發現我們收到了一個連線請求,問號後面的內容就是我們讀取到的檔案內容經過編碼後的字串:
Ps:
有時候也會出現報錯的情況(這是我們在漏洞的程式碼中沒有遮蔽錯誤和警告),比如我們這裡的payload沒有選用php的base64編碼,這裡報錯了,但是同時也將所讀取的內容爆了出來,只是特殊字元經過了HTML實體編碼。
內網探測
xxe 由於可以訪問外部 url,也就有類似 ssrf 的攻擊效果,同樣的,也可以利用 xxe 來進行內網探測。
可以先透過 file 協議讀取一些配置檔案來判斷內網的配置以及規模,以便於編寫指令碼來探測內網。
一個 python 指令碼例項:
執行起來大概是這樣
DDOS攻擊
該攻擊透過建立一項遞迴的 XML 定義,在記憶體中生成十億個”abc”字串,從而導致 DDoS 攻擊。原理為:構造惡意的XML實體檔案耗盡可用記憶體,因為許多XML解析器在解析XML文件時傾向於將它的整個結構保留在記憶體中,解析非常慢,造成了拒絕伺服器攻擊。
影響:
此漏洞非常危險, 因為此漏洞會造成伺服器上敏感資料的洩露,和潛在的伺服器拒絕服務攻擊。
防禦方法:
1. 禁用外部實體
2. 過濾和驗證使用者提交的XML資料
3. 不允許XML中含有任何自己宣告的DTD
4. 有效的措施:配置XML parser只能使用靜態DTD,禁止外來引入;對於Java來說,直接設定相應的屬性值為false即可
參考文章如下:
https://www.cnblogs.com/backlion/p/9302528.html
https://www.freebuf.com/vuls/175451.htmls
https://mp.weixin.qq.com/s/VWofHp5lJLYnbw01copnkw
https://www.freebuf.com/articles/web/97833.html
https://www.freebuf.com/articles/web/86007.html
相關文章
- Vue 從入門到放棄2019-12-30Vue
- Git 從入門到放棄2019-03-03Git
- GraphQL從入門到放棄2019-03-04
- Nginx從入門到放棄2020-09-30Nginx
- webpack從入門到放棄2018-03-07Web
- 推送 從入門到放棄2016-10-20
- Swift從入門到放棄2016-11-03Swift
- HTTP從入門到放棄2018-04-18HTTP
- openstack從入門到放棄2018-04-21
- JavaScript 從入門到放棄2016-04-12JavaScript
- NumPy從入門到放棄2024-08-08
- Spark從入門到放棄---RDD2020-08-17Spark
- 快取從入門到放棄2019-02-28快取
- webpack 從入門到放棄(一)2019-03-03Web
- swoole——從入門到放棄(一)2019-02-16
- 從入門到放棄 - 事件溯源2021-08-16事件
- swoole——從入門到放棄(三)2019-01-19
- FQ:從入門到放棄(二)2017-10-12
- 敏捷QA,從入門到放棄2016-08-10敏捷
- HTTP快取從入門到放棄2018-11-29HTTP快取
- Taro 小程式 從入門到放棄!2018-07-30
- t-SNE 從入門到放棄2021-10-13
- 設計模式從放棄到入門2017-12-28設計模式
- deepspeed從入門到放棄2024-09-01
- Scikit-learn從入門到放棄2024-08-18
- Elasticsearch從入門到放棄:再聊搜尋2020-07-14Elasticsearch
- Flink從入門到放棄-大綱2019-02-24
- Realm資料庫 從入門到“放棄”2019-03-02資料庫
- 分散式訓練從入門到放棄2019-04-11分散式
- 從入門到放棄之大資料Hive2019-05-12大資料Hive
- Redis從入門到放棄系列(十) Cluster2019-07-02Redis
- AOP埋點從入門到放棄(三)2018-08-21
- AOP埋點從入門到放棄(二)2018-08-12
- Spark從入門到放棄——初始Spark(一)2020-12-09Spark
- 從入門到放棄,我用了五年2020-09-24
- 從入門到放棄之promise用法(上)2018-06-14Promise
- Realm 資料庫 從入門到“放棄”2016-10-26資料庫
- JavaScript30秒, 從入門到放棄2017-12-25JavaScript