phpenv中禁用危险函数需修改当前版本生效的php.ini,正确设置disable_functions(无空格逗号分隔)和open_basedir(限定文件访问路径),并重启web服务验证。

phpEnv 没有“安全模式”(safe_mode)这个选项,它早在 PHP 5.4.0 就被彻底移除了,PHP 7+ 和所有现代版本(包括 phpEnv 支持的 PHP 7.4/8.x)根本不存在该配置项。你真正要做的,是禁用危险函数 + 限制文件访问范围。
phpEnv 下怎么找到并修改正确的 php.ini
phpEnv 是 Windows 上的多版本 PHP 环境管理工具,每个 PHP 版本都自带独立的 php.ini,但默认不启用,且路径容易搞错:
- 别去
C:\phpenv\php\php-8.2.10\这类目录下瞎翻 —— 那里只有原始安装包,实际生效的是C:\phpenv\php\php-8.2.10\php.ini-development或php.ini-production的副本 - 正确做法:在 phpEnv 托盘图标右键 → “Open PHP config” → 它会自动打开当前选中版本正在使用的
php.ini(通常是php.ini,不是 xxx-development) - 如果没反应,手动确认:用命令行运行
php --ini,看 “Loaded Configuration File” 输出的路径;或建一个info.php放进你的 Web 根目录,内容为<?php phpinfo(); ?>,浏览器访问后搜索 “Loaded Configuration File”
disable_functions 必须这么写才生效
phpEnv 默认的 php.ini 里 disable_functions 是空的或注释掉的。直接取消注释并填入函数名即可,但格式极其敏感:
- 必须用英文逗号分隔,不能有空格:写成
disable_functions = exec,system,shell_exec✅,写成disable_functions = exec, system, shell_exec❌(整行失效) - 推荐完整列表(覆盖常见绕过):
disable_functions = exec,passthru,shell_exec,system,proc_open,popen,pcntl_exec,pcntl_fork,pcntl_waitpid,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_alarm,pcntl_getpriority,pcntl_setpriority,dl,eval,assert,symlink,link,chmod,chown,chgrp,ini_set,ini_alter,ini_restore - 改完保存,必须重启 phpEnv 的 Web 服务(比如 Apache 或 Nginx)—— 单纯重启 phpEnv 托盘进程没用
光禁函数还不够,open_basedir 是关键补丁
攻击者禁用函数后仍可能通过写文件 + 二次包含执行代码(比如 file_put_contents('x.php', $_GET['c']); include 'x.php';)。open_basedir 能切断这个链条:
- 在同一个
php.ini文件里,找或添加这一行:open_basedir = C:/phpenv/www;C:/Windows/Temp;C:/phpenv/tmp - 把
C:/phpenv/www替换成你实际的网站根目录(比如C:/myproject),多个路径用分号;分隔(Windows 下不是冒号) - 确保包含临时目录(如
C:/Windows/Temp),否则上传、session、opcache 等功能会异常 - 该设置对
fopen、file_get_contents、include、require等全部文件类函数生效,比禁函数更底层
验证是否真禁用了,别信 phpinfo()
phpinfo() 只显示配置值,不反映运行时行为。必须实测调用:
- 新建
test.php,内容:<?php @exec('whoami', $out); var_dump($out); ?> - 访问页面,如果输出
NULL且 PHP 错误日志里出现Function exec is disabled,说明成功 - 再试绕过手法:
var_dump(function_exists('system'));应返回false;echo pcntl_fork() === false ? 'blocked' : 'ok';应输出blocked - 特别注意:phpEnv 默认同时提供 CLI 和 Web SAPI,
php -r "echo ini_get('disable_functions');"查的是 CLI 配置,和 Web 不一定一致,务必在浏览器里测
最常被忽略的一点:phpEnv 启动的 Apache/Nginx 是以 Windows 当前用户权限运行的,如果该用户本身有管理员权限,open_basedir 和 disable_functions 再严也挡不住本地提权后的任意操作。生产环境绝不该用 phpEnv,它只适合开发调试;上线前必须迁移到 Linux + FPM + 严格权限隔离的部署方式。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











