必须同时禁用eval和assert以阻断php rce,因assert在php 7.2–8.2中仍支持字符串参数且容错更高,可绕过仅禁eval的防护;需在php.ini的disable_functions中显式添加二者并重启服务验证生效。

禁用 eval 和 assert 是阻断PHP远程代码执行(RCE)最直接有效的手段。这两个函数在低防御配置下极易被攻击者利用,尤其当用户输入未经校验就传入时,一句话木马可直接落地。关键不在于“能不能用”,而在于“有没有必要用”——绝大多数业务场景完全可规避。
为什么必须同时禁用 eval 和 assert
eval() 是语言结构,将字符串当作PHP代码执行,语法要求严格(需分号结尾),但危害明确;assert() 本为调试断言函数,在 PHP 7.2–8.2 中仍支持字符串参数,且对语法容错更高,常被绕过作为 eval 的替代入口。PHP 8.3 虽标记其字符串模式为废弃,但未默认禁用,生产环境仍存在风险。
- 攻击者常用
?a=assert($_POST[1])或?a=eval($_POST[1])植入WebShell -
assert可嵌套调用eval,例如assert('eval(base64_decode("..."))') - 仅禁
eval不禁assert,等于留了一扇没锁的后门
通过 php.ini 彻底禁用函数
修改 php.ini 中的 disable_functions 是全局生效的首选方式,适用于 Apache、Nginx + PHP-FPM 等主流部署。
- 定位配置项:
disable_functions =(若被注释则删掉前面的分号) - 追加函数名,用英文逗号分隔:
eval,assert,system,exec,shell_exec,passthru,popen,proc_open,symlink,dl,ini_set - 特别注意:
assert必须显式列出,不能依赖版本弃用行为 - 保存后重启 Web 服务(如
systemctl restart php8.1-fpm nginx)
验证禁用是否真正生效
配置写完不验证,等于没做。推荐两种快速检测方式:
- 终端执行:
php -r "var_dump(function_exists('eval'), function_exists('assert'));",两个结果都应为 false - 新建
test.php放入 Web 目录:<?php echo eval('return 1+1;'); ?>,访问时应报错 Call to undefined function eval() - 额外检查:
php -i | grep disable_functions确认输出中包含你添加的函数名
禁用后还要防哪些绕过手法
单纯禁函数还不够。攻击者可能通过其他路径重建执行能力:
-
preg_replace('/.*/e', $_GET['p'], ''):旧版正则/e修饰符已废弃,但部分遗留系统仍在用,务必一并禁用或升级 -
create_function():本质是封装了eval,必须加入disable_functions -
unserialize()+ 魔术方法:虽不直接执行代码,但可触发危险操作,建议改用json_decode() - 第三方库自带
eval行为(如某些老旧模板引擎),需审计 vendor 目录
不复杂但容易忽略:禁用只是第一层,配合 open_basedir 限制文件作用域、关闭 allow_url_include、启用 opcache.enable 减少动态解析需求,才能形成纵深防御。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











