必须在php.ini和php-fpm pool中双重配置disable_functions,严格使用全小写、无空格、无换行、无末尾逗号的语法,禁用exec、system、proc_open、eval、assert等17个高危函数,并分别验证cli与web环境生效。

禁用PHP危险系统函数不能只改一行配置就完事,关键在写对、配全、验实——漏一个字符、少一次验证,防护就形同虚设。
必须禁用的核心函数列表
以下函数在PHP 8.5.7中仍可直接触发命令执行或动态代码解析,必须全部列入禁用清单:
- 命令执行类:exec, system, shell_exec, passthru, proc_open, popen, pcntl_exec
- 动态代码类:eval, assert(PHP 8.5.7仍支持字符串参数执行)
- 文件操作+辅助类:file_get_contents(防SSRF读敏感文件)、curl_exec(配合php://filter可包含恶意代码)、symlink, link, chmod, chown, chgrp, putenv, ini_set(防环境变量/配置绕过)
注意:函数名必须全小写,逗号之间绝对不能有空格,末尾不能多逗号,也不能换行。推荐写法:
disable_functions = exec,passthru,shell_exec,system,proc_open,popen,pcntl_exec,curl_exec,file_get_contents,eval,assert,symlink,link,chmod,chown,chgrp,putenv,ini_set
两处配置必须同时生效
仅改php.ini是不够的——FPM池配置优先级更高,且不可被运行时修改:
- 在php.ini中设置:disable_functions = ...
- 在/etc/php/8.5/fpm/pool.d/www.conf的[www]段内添加:
php_admin_value[disable_functions] = exec,passthru,...(必须用php_admin_value,不是php_flag) - 改完后执行:systemctl reload php8.5-fpm(reload比restart更稳妥,避免服务中断)
必须分别验证CLI和Web环境
phpinfo()显示值 ≠ 真生效。要实测调用是否报错:
-
Web端测试:新建test.php,内容为
<?php var_dump(exec('id')); ?>,访问后应输出NULL并带Warning提示“has been disabled” -
CLI端测试:运行
php -r "var_dump(system('id'));",同样需报Warning - 额外检查:
php -i | grep disable_functions和php -r "print_r(get_disabled_functions());",确认列表一致且无空值
防绕过:禁用只是起点,不是终点
攻击者不会只试exec——常见绕过点必须同步堵住:
- 确保
open_basedir已设(如/var/www/html:/tmp),防止file_put_contents写Shell后include执行 - 关闭
allow_url_include = Off和allow_url_fopen = Off,阻断远程包含 - Nginx/Apache中禁止上传目录执行PHP:
location ~ ^/upload/.*\.php$ { return 403; } - 若用PHP-FPM,确认
security.limit_extensions = .php,防.php5/.phtml绕过
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











