eval是php语言结构,非函数,故disable_functions无法禁用;须用php_diseval扩展、suhosin7补丁或运行时重定义等内核级手段拦截。

PHP 8.3 中 eval() 是语言结构,不是普通函数,因此无法通过 disable_functions 配置项禁用。仅靠修改 php.ini 无效,必须采用扩展级或内核层干预手段才能真正拦截其执行。
为什么 disable_functions 对 eval 无效
eval 在 PHP 中属于 Zend 引擎内置的语言构造(language construct),和 echo、isset 同类,不走函数调用栈,所以 disable_functions 完全不作用于它。即使你把它写进配置,重启服务后依然可以正常执行。
常见误区是以为加了就安全了,结果攻击者仍可通过 eval($_GET['code']) 或混淆载荷(如 eval(gzinflate(base64_decode(...))))直接 RCE。
PHP 8.3 可行的 eval 禁用方案
目前在 PHP 8.3 生产环境中稳定可用的方法有以下几种:
-
启用 php_diseval_extension 扩展:专为 PHP 8.2+ 设计,通过编译时注入 Zend 执行钩子,在 opcode 层直接拦截
eval调用。兼容宝塔、LNMP 等主流环境,无性能损耗。需下载源码、用对应 PHP 版本的phpize和php-config编译安装,并在 php.ini 中添加extension=php_diseval.so,最后重启 php-fpm。 -
使用 suhosin7 补丁版(适配 PHP 8.3):社区维护的 suhosin 分支已支持 PHP 8.3,启用后可在 php.ini 中设置
suhosin.executor.disable_eval = On。注意必须确认下载的是verified-for-php83标签版本,否则编译失败或运行异常。 -
手动重写内置函数(运行时拦截):适用于无法编译扩展的受限环境。在项目入口(如
index.php最顶端)加入:if (function_exists('eval')) {<br> function eval() { throw new ErrorException('eval disabled'); }<br> }
但该方式仅对后续定义的同名函数有效,无法覆盖 Zend 原生eval结构,实际防护效果极弱,仅作临时辅助。
必须同步做的加固措施
禁用 eval 只是纵深防御中的一环,单独做意义有限。务必配合以下操作:
- 关闭远程文件包含:
allow_url_fopen = Off和allow_url_include = Off - 限制文件操作范围:
open_basedir设置为 Web 根目录及必要子目录,禁止跨站读写 - 禁用其他高危函数:
system, exec, shell_exec, passthru, proc_open, popen, pcntl_exec, assert, file_put_contents, symlink, copy(这些仍可用disable_functions管控) - 上传目录禁止解析 PHP:
location ~ ^/upload/.*\.php$ { deny all; }(Nginx 配置) - 检查代码中所有动态执行逻辑,将
eval替换为白名单表达式解析器或ast\literal_eval类思路(如需解析简单计算,可用operator模块 + 字符串校验)
验证是否生效
部署后务必实测验证,不能只看配置是否写入。新建一个测试脚本,内容为:<?php eval('echo "test";'); ?>
访问该页面,应返回 500 错误或明确报错(如 “eval disabled”、“Call to undefined function eval” 或空白页+错误日志),而非输出 test。
同时检查 phpinfo() 页面中的 “disable_functions” 列表是否包含你配置的函数,以及 “Loaded Configuration File” 路径是否正确,避免改错配置文件。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











