必须禁用exec、system、shell_exec、passthru、proc_open、popen、pcntl_exec、assert、putenv、ini_set;需按场景评估file_put_contents、copy、symlink等;配置须全小写、无空格、逗号分隔,并修改fpm pool配置后重启php-fpm,且cli与web双端实测验证。

禁用 PHP 危险函数不是“越多越好”,而是要精准切断攻击链中最常被利用的执行入口。真正起效的 disable_functions 配置,必须聚焦三类能直接落地执行、绕过检测、或配合其他漏洞形成闭环的函数,同时避开误禁导致业务中断的坑。
必须禁用的核心高危函数(RCE 关键入口)
这些函数在绝大多数 WebShell(如 AntSword、China Chopper)和自动化攻击工具中默认优先调用,禁用后可直接阻断基础命令执行能力:
- exec、system、shell_exec、passthru:直通 shell,参数拼接即触发命令执行,首当其冲必须禁
- proc_open、popen、pcntl_exec:比 exec 更隐蔽,返回资源句柄,日志难追踪;FPM 环境下常绕过 WAF 和简单检测,必须列入
-
assert:PHP 8.3 仍支持字符串参数(
assert("phpinfo()")),是 eval 类行为最常见替代入口,务必禁用 - putenv、ini_set:虽不直接执行代码,但可配合 open_basedir 绕过、环境变量污染或 JIT 漏洞利用,建议同步禁用
需按场景评估的中风险函数(非一刀切)
这些函数本身不执行命令,但在路径控制失效(如未配 open_basedir)或存在文件上传/日志包含漏洞时,可能成为 WebShell 落地关键环节:
-
file_put_contents、copy、symlink:可写入恶意脚本或构造软链绕过路径限制,若已设严格
open_basedir且上传目录隔离,可酌情保留 -
curl_exec、file_get_contents:主要风险在于 SSRF 或
php://filter读取敏感文件,禁用会影响正常 HTTP 客户端逻辑,建议优先靠网络策略和输入过滤防控 - unserialize、eval:eval 无法禁用(属语言结构),unserialize 本身无害,危险在于反序列化链——禁它会直接让 Laravel、Symfony 等框架崩溃,不应加入列表
配置写法与生效验证的关键细节
90% 的“已配置却无效”问题,源于语法错误或作用域遗漏:
- 函数名必须全小写:
exec,system,passthru✅;EXEC,SYSstem❌ - 逗号为唯一分隔符,前后禁止空格:
exec,system,passthru✅;exec, system❌(system 实际未被识别) - FPM 环境下,
www.conf中的php_admin_value[disable_functions]优先级高于php.ini,宝塔等面板用户务必检查并修改对应 pool 配置 - 必须重启
php-fpm进程(systemctl restart php84-fpm),reload Nginx/Apache 不触发重载 - 验证不能只查
function_exists()或phpinfo()显示值,要实测调用:/www/server/php/84/bin/php -r "var_dump(system('id'));"应报 Warning 并返回 NULL
禁用不是终点,而是组合防御的一环
仅靠 disable_functions 无法覆盖所有绕过路径。攻击者一旦获得文件写入权限,仍可通过 include、require 加载未被禁用的 PHP 脚本执行任意代码。因此必须同步落实:
- 严格设置
open_basedir(如/var/www/html:/tmp),限制所有 I/O 操作边界 - 关闭
allow_url_include = Off和allow_url_fopen = Off,堵死远程文件加载 - FPM 下启用
security.limit_extensions = .php,防止.phtml、.php5绕过解析 - PHP 7.4+ 可设
opcache.restrict_api = "/dev/null",防止信息泄露与 JIT 利用
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











