include和require本身无安全之分,危险源于参数可控且未校验;PHP 7.4中LFI仍高危,需用白名单映射绝对路径、realpath校验、显式拦截伪协议(如php://filter)、禁用allow_url_include并配置open_basedir。

include 和 require 本身没有安全或不安全之分,危险来自参数是否可控、是否经过校验。PHP 7.4 及以上版本虽默认关闭 allow_url_include,但本地文件包含(LFI)仍可读取日志、会话、临时文件,甚至通过 php://filter 直接泄露源码。
别拼路径,用白名单查绝对路径
最稳妥的方式是完全避免字符串拼接。用户输入只作为键,映射到预定义的完整绝对路径:
- 定义白名单时直接写死绝对路径,例如:
$pages = ['home' => '/var/www/html/app/views/home.php', 'user' => '/var/www/html/app/views/profile.php']; - 获取参数后不做任何过滤或截断处理,直接查键:
$page = $_GET['p'] ?? ''; if (isset($pages[$page])) { include($pages[$page]); } - 每个路径建议预先用
realpath()校验一次,确保不是软链接跳转出根目录,比如:realpath($pages[$page]) === $pages[$page]
禁用伪协议和非法包装器
即使用了白名单,攻击者仍可能传入 php://filter 等协议绕过。需在代码层显式拦截:
- 检查参数是否含
://,发现即拒绝:if (strpos($page, '://') !== false) die('Invalid path'); - 特别注意
data://、php://、phar://、expect://等常见危险协议 - 配合 php.ini 设置:
allow_url_include = Off(默认已关),open_basedir = /var/www/html/(限制可访问根目录)
慎用 basename() 和后缀拼接
看似加了 .php 后缀或用 basename() 过滤,实际极易被绕过:
-
basename($_GET['p']) . '.php'对?p=../../etc/passwd%00无效——%00在部分环境中仍会截断 -
include('pages/' . $_GET['p'] . '.php')中,$_GET['p']是../config就能跳出目录 -
basename()不处理 URL 编码,?p=..%2F..%2Fetc%2Fpasswd可绕过纯字符串匹配
require 和 include 的选择不影响漏洞等级
两者在漏洞利用上无本质区别:
-
include出错继续执行,适合非关键模块,但错误提示可能暴露路径信息 -
require出错直接终止,适合核心配置,但攻击者仍可在报错前完成利用(如先写入日志再包含) -
_once版本仅防重复加载,不防路径控制,对安全无实质提升
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











