必须关闭allow_url_include以防止远程代码执行,应编辑php.ini设为Off并重启Web服务,或用.htaccess/user.ini覆盖;同时需代码层白名单校验、禁用php://等危险协议,并检查CLI与Web SAPI配置一致性。

必须关掉 allow_url_include,否则只要代码里有 include 或 require 拼接用户输入,就可能被远程加载并执行恶意脚本——哪怕你没开 allow_url_fopen,php:// 协议仍能绕过。
怎么确认并关闭 allow_url_include
它默认是 Off,但很多旧版 WAMP/XAMPP、一键包或共享主机环境会误设为 On。别只看配置文件有没有这行,得用 phpinfo() 页面查运行时真实值。
- 编辑
php.ini,找到或添加:allow_url_include = Off - 改完必须重启 Web 服务(Apache / nginx + php-fpm / Apache 的
mod_php),否则不生效 - 无权限改
php.ini?Apache 可用.htaccess:php_flag allow_url_include off;PHP 5.3+ 支持user.ini,写入同上内容即可 - 顺手把
allow_url_fopen = Off也关了——它不影响include,但能拦住大量基于file_get_contents()或fopen()的 RFI 利用链
为什么关了配置还不够?白名单才是硬防线
就算 allow_url_include = Off,攻击者仍可用 php://filter/read=convert.base64-encode/resource=/etc/passwd 这类伪协议读取任意本地文件,或者通过路径遍历(../../../)包含日志、session、上传的图片马等。
- 永远不要写
include $_GET['page'] . '.php';这种代码 - 首选白名单数组:
$valid_pages = ['home', 'about', 'contact']; if (in_array($_GET['page'], $valid_pages)) { include __DIR__ . '/pages/' . $_GET['page'] . '.php'; } - 若必须动态拼接,至少用
basename()剥离路径:include basename($_GET['page']) . '.php';,但仍有风险,仅作兜底 - 配合
open_basedir限制可访问目录范围,比如设为/var/www/html,让../遍历直接失败
include 相关函数的实际差异与误用点
很多人以为 include_once 或 require_once 更安全,其实它们和 include/require 在参数校验上完全没区别,只是重复包含控制逻辑不同。
立即学习“PHP免费学习笔记(深入)”;
-
include:出错仅警告,脚本继续执行 —— 攻击者可能利用这点试探路径 -
require:出错直接中止 —— 表面更“严格”,但一旦被绕过,后果一样严重 -
include_once/require_once:加了已包含判断,对安全无实质提升 - 所有这四个函数,只要参数含用户输入且未过滤,就是高危入口
最常被忽略的是 CLI 和 Web SAPI 配置不一致:Web 环境关了 allow_url_include,但 PHP CLI 模式下仍是 On,如果后台任务或定时脚本用了 include 动态加载,照样中招。务必用 php -i | grep allow_url_include 分别检查两个 SAPI 的实际值。



















