PHP 7.0+ 已彻底移除 /e 修饰符,升级版本可根本消除风险;若需兼容旧版,必须改用 preg_replace_callback 替代,并严格校验输入、禁用危险字符,防止用户输入触发代码执行。

直接禁用 /e 修饰符,是修复 preg_replace 代码执行漏洞最根本、最有效的办法。PHP 7.0+ 已彻底移除该修饰符,所以升级 PHP 版本本身就能消除风险;若仍运行在 PHP 5.x 环境,则必须从代码层规避。
替换为安全的函数组合
用 preg_replace_callback 替代带 /e 的 preg_replace,把动态逻辑显式封装进回调函数中,避免字符串被当代码解析:
- 错误写法(危险):
preg_replace('/(\d+)/e', 'intval("$1") * 2', $str) - 正确写法(安全):
preg_replace_callback('/(\d+)/', function($m) { return intval($m[1]) * 2; }, $str)
这样既保留正则能力,又将执行上下文严格控制在 PHP 函数体内,用户输入无法突破作用域。
严格过滤输入参数
如果因历史原因无法立即重构,至少要对传入 preg_replace 的 $pattern 和 $replacement 做白名单校验:
立即学习“PHP免费学习笔记(深入)”;
- 禁止
$pattern中出现/e、/E、@e、@E等修饰符组合 - 对
$replacement进行字符级限制:只允许字母、数字、下划线、点号、斜杠及少量安全符号,拒绝单/双引号、美元符、分号、括号等可构成表达式的字符 - 可用正则快速拦截:
if (preg_match('/[\'"$;(){}\[\]]/', $replacement)) die('Invalid replacement');
升级 PHP 并禁用危险配置
PHP 7.0 起已废弃并移除 /e 修饰符,调用会直接报错;若仍用 PHP 5.6 或更早版本,务必:
- 尽快升级到受支持的 PHP 版本(如 8.1+)
- 检查
php.ini中是否启用disable_functions,可追加preg_replace(但需确认业务无依赖,否则慎用) - 在 Web 服务器层(如 Nginx)对含
/e、@e的 URL 参数做规则拦截,作为纵深防御补充
框架与 CMS 的专项修复
ThinkPHP 2.x 等老框架曾因类似写法爆出高危漏洞,典型修复方式是:
- 将
preg_replace(..., '$var["\1"] = "\2";', ...)中的双引号替换为单引号,防止变量解析 - 更新至官方已修复版本(如 ThinkPHP 3.2.3+ 或 ThinkPHP 5.x)
- 审计所有自定义路由、分发器、模板解析模块,排查是否存在动态拼接
preg_replace参数的行为



















