这种eval用法有什么问题?旧WooCommerce插件PHP语法错误如何修复
错误原因
你遇到的语法错误是这个自定义custom_json_decode函数的逻辑缺陷直接导致的:
- 该函数没有处理输入JSON中的HTML实体,
<这类转义字符没有被还原就直接拼接进了待执行的代码,执行eval时就会报意外的<字符错误 - 引号转义判断逻辑错误,无法正确识别被转义的双引号,导致注释状态判断错乱,后续的字符替换完全不符合预期,最终生成的PHP代码存在语法问题
- 本身使用
eval处理用户输入属于极高危操作,只要输入被恶意构造,攻击者可以直接执行任意代码拿到服务器权限,这个实现从设计上就有严重问题
修复方案
方案一(优先推荐):替换为PHP原生实现
PHP 5.2及以上版本都内置了json_decode函数,完全可以替代这个有问题的自定义实现,性能和安全性都有数量级提升。如果原函数是为了兼容带注释的非标准JSON,只要加一步注释过滤即可:
public function custom_json_decode( $json ){ // 还原输入中的HTML实体 $json = html_entity_decode($json, ENT_QUOTES); // 过滤JSON中的单行、多行注释,适配非标准JSON格式需求 $json = preg_replace('!/\*.*?\*/!s', '', $json); $json = preg_replace('/\n\s*\/\/.*$/m', '', $json); // 原生解析,返回对象和原函数输出完全兼容 return json_decode($json); }
方案二(临时兼容,不推荐长期使用):修复原函数逻辑
如果暂时不能替换原有实现,可以先修复原函数的逻辑缺陷规避报错,注意该方案依然保留了eval的安全风险,仅可作为临时过渡方案:
public function custom_json_decode( $json ){ // 先还原所有HTML实体,避免转义字符导致语法错误 $json = html_entity_decode($json, ENT_QUOTES); $comment = false; $out = '$x='; $len = strlen($json); for ($i=0; $i<$len; $i++) { if (!$comment) { if (($json[$i] == '{') || ($json[$i] == '[')) $out .= ' array('; else if (($json[$i] == '}') || ($json[$i] == ']')) $out .= ')'; else if ($json[$i] == ':') $out .= '=>'; else // 转义特殊字符避免语法错误 $out .= addcslashes($json[$i], "'\\"); } else $out .= addcslashes($json[$i], "'\\"); // 修复引号转义判断逻辑,正确识别非转义的双引号 if ($json[$i] == '"' && ($i == 0 || $json[$i-1] != '\\')) $comment = !$comment; } @eval($out . ';'); return ( object )$x; }
内容的提问来源于stack exchange,提问作者Tassos Voulgaris
相关产品推荐
相关产品推荐

