禁用 system 后仍可调用 passthru,因 disable_functions 仅按函数名精确匹配,未禁用 passthru 等函数;常见疏漏包括配置含空格、多层覆盖、Suhosin 独立黑名单等。

为什么禁用 system 后还能调用 passthru?
PHP 的 disable_functions 是按函数名精确匹配的,不是按功能类别禁用。你只写了 system,exec、shell_exec、passthru、proc_open 等全都不受影响。这些函数底层都可能触发 shell 调用,但 PHP 不会自动推导关联性。
常见疏漏点:
-
disable_functions值是逗号分隔字符串,**不能有空格**(如"system, exec"会导致exec实际未被禁用) - 某些扩展自带函数(如
pcntl_exec、curl_exec配合file://协议)不在默认黑名单里 - 如果用了 Suhosin 补丁,它有自己的
suhosin.executor.func.blacklist,和disable_functions是两套机制
如何检查当前真正生效的禁用函数列表?
别只信配置文件,运行时可能被覆盖。最可靠方式是直接在 PHP 中查:
注意:function_exists() 对被禁用函数返回 false,这是最准的运行时判断依据。很多线上环境因多层配置(php.ini / .user.ini / docker-entrypoint.sh)导致最终生效值和预期不一致。
立即学习“PHP免费学习笔记(深入)”;
绕过 disable_functions 的常见路径有哪些?
攻击者常从这几个非典型入口突破:
-
mail()函数的第五个参数($additional_parameters)可注入 shell 命令(需 sendmail 配置支持) -
error_log()写入文件时配合expect://或php://filter协议触发代码执行(取决于allow_url_include和 stream wrapper 注册状态) -
unserialize()+ POP 链调用__wakeup/__destruct中的危险方法(如ReflectionFunction构造后调用invoke) - 某些扩展函数:如
imap_open()(配合ssl://和恶意证书回调)、exif_thumbnail()(解析恶意图片触发内存操作)
这些不是 disable_functions 的管控范围,得靠关闭对应扩展或限制协议(如 stream_wrapper_unregister("expect"))来防御。
生产环境推荐的最小化禁用列表
仅禁用明确不需要的函数远远不够。以下是一组经过验证、兼顾兼容性与安全性的基础清单(适用于多数 Web 应用):
disable_functions = system,exec,shell_exec,passthru,proc_open,proc_get_status,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_exec,pcntl_alarm,pcntl_getpriority,pcntl_setpriority,dl,assert,create_function,eval,call_user_func,call_user_func_array,register_shutdown_function,set_error_handler,set_exception_handler,ini_set,mail
关键点:
- 必须包含所有
pcntl_*系列——它们能绕过大部分进程级限制 -
mail要禁,否则可能成为命令注入出口 -
assert和eval在 PHP 7.2+ 已默认禁用高危用法,但仍建议显式加入 - 若应用不用日志记录到远程,可额外加
error_log;若用 Composer 自动加载,慎禁class_alias等反射类函数
改完记得重启 PHP-FPM 或 Apache,并用 php -m 确认无冲突扩展启用。最易被忽略的是:Docker 容器中 php.ini 修改后没重建镜像,或 .htaccess 里又用 php_admin_value 覆盖了设置。











