必须同时配置disable_functions、open_basedir和opcache.restrict_api,并确认cli/web环境对应php.ini路径;禁用列表须小写、无空格、含pcntl_exec/proc_open等全量高危函数,且需实测写入+执行闭环验证。

禁用危险函数不能只改 disable_functions 一行就完事——PHP 7.4 下它依然会被 pcntl_exec、proc_open 或文件写入+动态执行绕过。
怎么找到真正生效的 php.ini 文件
很多人改了错的配置文件,重启后毫无效果。PHP CLI 和 Web SAPI(如 FPM/Apache)各自加载独立的 php.ini,必须确认当前环境用的是哪一份:
- Web 环境:新建
info.php,内容为<?php phpinfo(); ?>,访问后搜索 “Loaded Configuration File” - CLI 环境:运行
php --ini,看 “Loaded Configuration File” 行,不是 “Configuration File (php.ini) Path” - FPM 场景下,常见路径是
/etc/php/7.4/fpm/php.ini,改完必须sudo systemctl reload php7.4-fpm
disable_functions 列表必须显式写全,且不能有空格
PHP 7.4 不再支持 dl(),但 pcntl_* 系列仍完整存在,且常被用于绕过传统禁用。别信“只禁 exec 就够了”的说法:
- 必须包含:
exec,passthru,shell_exec,system,proc_open,popen,pcntl_exec,pcntl_fork,pcntl_waitpid,pcntl_wait,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 - 逗号之间**绝对不能有空格**,否则整行失效,PHP 启动时可能静默忽略
- 大小写敏感:
Eval不会禁掉eval,必须小写 - 别名函数也要单独列:
ini_alter是ini_set的别名,两者都得写上
光禁函数没用,必须配合 open_basedir 和 opcache.restrict_api
攻击者能写入文件(比如上传 /tmp/shell.php),再用未被禁用的函数(如 include、require_once)加载执行,disable_functions 就形同虚设:
-
open_basedir = /var/www/html:/tmp:限制所有文件操作只能在这两个路径内,/tmp必须包含,否则上传、缓存会失败 -
opcache.enable = 1且opcache.restrict_api = "/dev/null"(PHP 7.4+ 支持):防止通过opcache_get_status()泄露脚本路径或触发 JIT 相关利用 - 若用 Nginx + PHP-FPM,务必检查
security.limit_extensions = .php,避免.phtml、.php5绕过解析
验证必须走执行流,不能只看 phpinfo 或 function_exists
function_exists('exec') 返回 false 只说明函数不可见,不代表调用一定失败;攻击者更关心能否完成“写入 → 加载 → 执行”闭环:
- 实测组合行为:
@file_put_contents('/tmp/test.php', '<?php system($_GET[1]);?>');看是否写入成功 - 再访问
/tmp/test.php?1=id,看是否真能执行——这才是关键验证点 - 同时测试
proc_open('id', [], $pipes)是否返回 resource 或 false - 日志里搜
"has been disabled for security reasons",而不是只看页面有没有输出
最易被忽略的一点:Web 服务器配置比 PHP 配置更容易出问题。Nginx 若写了 fastcgi_param SCRIPT_FILENAME $request_filename,攻击者上传 shell.php 到任意目录都能直接执行,disable_functions 再严也没用。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











