发布于2026-07-15 阅读(0)
扫一扫,手机访问
可以明确告诉你:PHP 7.4虽然已经彻底移除了register_globals,但变量覆盖漏洞可没跟着消失。问题的根源,仍然在extract()、parse_str()以及手动的赋值逻辑上。

register_globals,但变量覆盖漏洞仍存在,根源在 extract()、parse_str() 和手动赋值逻辑首先得明确一点:PHP 7.4 不再支持 register_globals(这个配置早在 PHP 5.4 就被废弃,5.6+ 就已经完全删除了)。所以,你不用担心因为 ini 设置错误,导致“自动注册 GET/POST 变量为全局”。但问题在于,开发者自己写的代码,依然可能触发覆盖——比如用 extract($_GET) 把用户输入直接变成变量,或者在循环中反复用 = 覆盖同名变量。
extract() 是最常被忽略的覆盖入口,必须加白名单或禁用extract() 绝对是个高危操作,很多开发者都在它身上栽过跟头。它会把数组的键名直接转为变量名并赋值,攻击者可以借此轻松覆盖已有变量——比如 $flag、$is_admin 这类关键变量。
extract($_GET) 允许你传个 ?user_id=123&is_admin=1,就能直接覆盖 $is_admin 的值。EXTR_OVERWRITE(默认模式),它会无条件覆盖所有变量。extract($_GET, EXTR_IF_EXISTS, ['user_id', 'page', 'sort']),这样只有白名单里的变量才会被处理。extract(),改为显式赋值:$user_id = $_GET['user_id'] ?? null;,清晰明了。$allowed = array_intersect_key($_GET, array_flip(['user_id', 'page'])); extract($allowed);,这样能确保只有你想用的变量被提取出来。= 和 .= 的区别决定是否覆盖这个错误相当常见,尤其是在循环里用 = 赋值,结果只保留了最后一次循环的结果:
$out = "$key: $value"; → 每次循环都重置 $out,最终只剩最后一项。$out .= "$key: $value\n"; → 累积拼接,但前提是你要先初始化 $out = '';。implode() 合并:$lines[] = "$key: $value"; echo implode("\n", $lines);,这样既安全又高效。$out 在函数外定义,又在函数内用 global $out 修改,那又回到了全局变量污染的老路。正确的做法是参数传入 + 返回值输出。PHP 7.4 支持带类型和可见性的属性声明,这是防意外覆盖的底层防线,比单纯依赖命名规范要靠谱得多:
private 或 protected 替代 public 属性,从根本上阻止外部直接赋值:private string $token;public const,且不可修改:public const API_TIMEOUT = 30;(define() 是全局的、无命名空间、不支持类型,已经基本淘汰了)。$this->token = $_GET['t'];,而应走 setter 并校验:public function setToken(string $t): void { if (ctype_alnum($t)) $this->token = $t; },这样能确保数据安全。private static + 静态方法控制,而不是依赖全局变量。必须警惕的是,真正难防的不是语法限制,而是开发者在“图省事”时,绕过类型检查、跳过白名单、滥用 extract(),或者在闭包里隐式捕获并修改父作用域变量——这些行为在 PHP 7.4 下依然有效,也依然危险。
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
正版软件
正版软件
正版软件
正版软件
正版软件
1
2
3
7
8