PHP 8.2 禁用危险函数是防御文件包含漏洞的关键一环,但需结合 open_basedir 限制、关闭远程包含及白名单包含逻辑才能有效防护;必须重启 php-fpm 生效并实测验证。

PHP 8.2 中禁用危险函数不能单独解决文件包含漏洞,但它是关键一环——它能阻断攻击者在利用文件包含(如 include($_GET['page']))后进一步执行命令、写入 Webshell 或提权的路径。真正降低风险,需将函数禁用与路径限制、输入控制结合使用。
禁用核心执行类函数(必须操作)
这些函数一旦被调用,常构成“包含→写入→执行”攻击链的最后一环。在 PHP 8.2 中仍有效且高危:
-
system、exec、shell_exec、passthru:直接执行系统命令 -
proc_open、popen、pcntl_exec:更隐蔽的进程控制方式,绕过简单黑名单常见 -
eval、assert(PHP 8.2 中assert默认为函数行为,非语言结构)、create_function(已废弃但部分旧代码仍存在):用于动态代码执行,配合文件包含极易落地 Webshell -
file_put_contents、symlink、copy:虽非执行函数,但可写入恶意 PHP 文件,为后续包含铺路
配置方法:编辑 实际生效的 php.ini(通过 phpinfo() 查 “Loaded Configuration File” 路径),修改或添加:
⚠️ 注意:逗号后不可有空格;全部小写;不能换行;改完必须重启 php*-fpm(如 systemctl restart php8.2-fpm),reload 不生效。
立即学习“PHP免费学习笔记(深入)”;
强制 open_basedir 限制文件操作范围
即使攻击者绕过函数禁用(例如通过未禁用的扩展或反序列化链),open_basedir 能让绝大多数文件包含和写入类 payload 失效——因为无法跳出指定目录读取 /etc/passwd,也无法写入 Web 可访问路径。
在 php.ini 中设置:
open_basedir = /var/www/html:/tmp:/var/www/session✅ 确保包含:
– 网站根目录(如 /var/www/html)
– 临时目录(/tmp,供 session、upload 使用)
– 若应用自定义 session 路径,也需加入
❌ 避免设为 / 或留空,否则完全失效;也不建议只写一个路径导致上传失败等异常。
关闭远程包含并加固包含逻辑本身
禁用函数是“堵下游”,而这一项是“截上游”:
- 在 php.ini 中设
allow_url_fopen = Off和allow_url_include = Off,彻底禁止http://、php://filter等协议参与包含 - 代码层改用白名单机制:不拼接用户输入,而是映射到预定义数组,例如:
$pages = ['home' => '/inc/home.php', 'about' => '/inc/about.php'];<br>if (isset($pages[$_GET['p']])) { include $pages[$_GET['p']]; } - 若必须动态包含,务必对输入做
basename()+ 正则校验(仅字母数字下划线点号)+realpath()目录比对
验证是否真起作用
别只看 function_exists('exec') 返回 false——那只是函数不可见,不代表调用被拦截。必须实测执行流:
- 新建
test.php:<?php @exec('id', $o); print_r($o ?: 'exec blocked'); ?> - 访问页面,应看到
Warning: exec() has been disabled for security reasons或输出exec blocked - 再试写入:
@file_put_contents('/tmp/test.php', '<?php phpinfo();?>');,然后检查/tmp/test.php是否真的没生成 - CLI 下也要验证:
php -r "echo exec('whoami');",避免 FPM 和 CLI 配置不一致



















