修复PHP变量覆盖漏洞需从函数调用、参数处理、配置控制三方面同步加固:禁用extract()等危险函数并规范用法,初始化变量并白名单过滤键名,关闭register_globals,强化入口过滤与模板层防护。

修复PHP变量覆盖漏洞,关键在切断“用户输入→变量名/值可控→逻辑篡改”这条链路。不能只堵一个点,得从函数调用、参数处理、配置控制三方面同步加固。
禁用或严格约束危险函数
extract()、parse_str()、import_request_variables() 是高危源头,优先排查代码中是否直接使用:
- 用 extract($arr, EXTR_SKIP) 替代默认调用,避免覆盖已有变量
- parse_str() 必须显式传入目标数组,禁止无第二个参数的写法(如 parse_str($_GET['data'], $output))
- 彻底移除 import_request_variables()(PHP 5.4+ 已废弃),改用 $_GET/$_POST 显式赋值
- 检查所有 $${$key} 类型的可变变量用法,确认 $key 是否完全可控;若不可信,加白名单校验
初始化所有可能被覆盖的变量
未初始化的数组键或局部变量,容易被用户输入通过 foreach 或 extract 覆盖:
- 在使用前主动声明空数组:$updateinfo = [];、$where = '';
- 对多维数组赋值,避免直接遍历 $_POST 合并:不写 foreach($_POST as $k=>$v) { $data[$k] = $v; },改用白名单过滤键名
- DedeCMS 类典型问题:在 /include/common.inc.php 中,将 ${$_k} = addslashes($_v) 改为仅处理预设键名(如 'cfg_dbprefix')
关闭全局变量自动注册与强化入口过滤
register_globals=On 是历史遗留雷区,虽 PHP 5.4+ 已移除,但老系统仍需确认:
立即学习“PHP免费学习笔记(深入)”;
- php.ini 中设 register_globals = Off(必须项)
- ThinkPHP 等框架需在入口文件(如 public/index.php)开头拦截:if (isset($_POST['_method']) && in_array(strtolower($_POST['_method']), ['__construct', '__destruct'])) die('Access Denied');
- 对 $_REQUEST、$_GET['s'] 等高频攻击入口做关键词过滤,如屏蔽 think|invokefunction|call_user_func
模板与控制器层额外防护
变量覆盖常配合模板引擎执行,需阻断后续利用链:
- 禁用 assign() 接收非标数组,或在调用前校验键名合法性(如只允许字母数字下划线)
- 模板缓存路径不要依赖用户输入;若需动态指定,强制限定目录范围(如 realpath($path) === realpath(ROOT_PATH . 'cache'))
- ThinkPHP 中显式设置 'var_method' => '' 并关闭 auto_route,防止路由阶段被绕过



















