文件包含漏洞利用核心是让PHP执行非预期文件,攻击者通过控制include类函数参数实现,常见手法包括目录穿越、伪协议滥用、日志/会话文件注入及图片马等,防御需白名单映射、realpath校验、open_basedir限制及关闭危险配置。

文件包含漏洞怎么被利用
攻击者主要通过控制 include、require、include_once、require_once 这类函数的参数,让PHP加载并执行非预期文件。关键不在于“能不能读”,而在于“读完之后会不会被当代码执行”。例如:
- 传入
../../../../etc/passwd→ 读取系统用户列表(纯文本输出) - 传入
php://filter/convert.base64-encode/resource=index.php→ 直接获取源码Base64编码,解码即得完整逻辑 - 传入
../../var/log/apache2/access.log→ 若日志中含恶意请求(如<?php system($_GET['cmd']);?>),可触发RCE - 传入
session_start()生成的会话文件路径(如/var/lib/php/sessions/sess_abc123)→ 注入PHP代码后包含执行 - 配合上传功能,上传带PHP代码的图片(“图片马”),再用
../upload/xxx.jpg包含触发
常见绕过手法有哪些
防御若只做简单过滤,往往一击即破。实际环境中高频出现的绕过包括:
-
目录穿越未拦干净:只过滤一次
../,但攻击者用....//、%2e%2e%2f、..%2f..%2f多层编码绕过 -
空字节截断残留风险:虽PHP 7.4+默认禁用 magic_quotes_gpc,但某些旧容器或自编译环境仍响应
%00,导致config.php%00.jpg被截断为config.php -
伪协议滥用:
php://input需allow_url_include=On;data://和expect://则依赖扩展是否启用;phar://在反序列化场景中可触发任意类加载 - 白名单校验失效:仅检查文件名是否在数组里,却没验证该文件真实路径是否合法,攻击者可通过符号链接指向任意位置
真正有效的防御怎么做
靠单点过滤(比如删../或替换%00)无法闭环。必须分层落实:
-
代码层:白名单映射绝对路径——不用拼接,用关联数组直接映射键到完整绝对路径,例如:
$whitelist = ['home' => '/var/www/html/pages/home.php', 'about' => '/var/www/html/pages/about.php'];if (isset($whitelist[$_GET['page']])) { include($whitelist[$_GET['page']]); } -
运行时校验:realpath + open_basedir 双保险——对白名单中每个路径预先调用
realpath(),确认其落在允许目录内;同时启用open_basedir限制PHP可访问的根路径 -
配置层加固——关闭高危选项:
allow_url_include = Off、禁用危险函数:disable_functions = system,exec,passthru,shell_exec,proc_open -
避免动态后缀拼接——不要写
include($_GET['f'] . '.php'),这种模式天然存在后缀绕过可能(如传config%00或利用Windows路径特性)
为什么很多修复看起来安全实则无效
典型误区是把防御当成“堵输入”,而不是“控行为”。例如:
- 只用
basename()提取文件名 → 攻击者传../../etc/passwd,basename返回passwd,看似无害,但后续拼接仍可能还原路径 - 仅用
in_array()校验参数值 → 白名单是['a.php','b.php'],但攻击者传a.php\0../config.php,部分环境下仍可截断生效 - 加了
.php后缀就以为安全 → 忘了php://filter等协议根本不需要后缀,也不走文件系统 - 依赖WAF规则拦截关键词 → 伪协议载荷可多层URL编码、大小写混用、插入空白符,规则极易被绕过
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











