首页
/ PHP源码中extract()函数EXTR_REFS参数的UAF漏洞分析

PHP源码中extract()函数EXTR_REFS参数的UAF漏洞分析

2025-05-02 08:11:49作者:幸俭卉

在PHP语言的核心实现中,extract()函数是一个用于将数组中的键值对导入当前符号表的实用工具。当开发者使用EXTR_REFS标志时,函数会将数组元素作为引用导入。然而,这个功能在特定场景下会触发一个危险的内存安全问题。

问题原理

该问题源于对象析构与引用计数管理之间的时序问题。当以下两个条件同时满足时就会触发:

  1. 被extract()操作的数组键名与全局变量名相同
  2. 该全局变量是一个对象,且其析构函数会主动unset这个全局变量

示例中的关键代码展示了典型的触发场景:

class GetFree {
  public function __destruct() {
    unset($GLOBALS['b']);
  }
}

$b = new GetFree;
$array = array("b" => "AB");
extract($array, EXTR_REFS);

底层机制分析

在PHP引擎执行过程中,这个问题涉及以下几个关键步骤:

  1. extract()开始处理数组时,首先会获取目标符号表中已存在的变量
  2. 当EXTR_REFS标志启用时,函数会尝试建立引用关系
  3. 在建立引用过程中,如果原始变量是对象,会触发引用计数调整
  4. 如果此时对象的析构函数被调用并unset了全局变量,会导致后续的引用计数操作访问已释放的内存

从ASAN报告可以看出,崩溃发生在zend_gc_delref的引用计数递减操作时,此时对象存储空间已被释放。

影响范围

这个内存安全问题会影响:

  • 所有使用EXTR_REFS参数的extract()调用
  • 涉及在析构函数中操作全局变量的场景
  • PHP 8.3及更高版本

虽然需要特定条件才能触发,但在复杂的应用场景中,特别是使用魔术方法或依赖全局状态管理的代码中,风险会显著增加。

解决方案

PHP开发团队通过以下方式修复了该问题:

  1. 在extract()操作前增加引用计数保护
  2. 确保在建立引用关系期间对象保持有效状态
  3. 优化了变量导入过程中的引用计数管理时序

修复后的实现保证了即使遇到析构函数中的unset操作,也能安全地完成引用建立过程,避免了内存安全问题情况的发生。

开发者建议

对于需要使用类似功能的开发者,建议:

  1. 避免在对象析构函数中操作可能被extract()处理的全局变量
  2. 谨慎使用EXTR_REFS参数,特别是在不确定变量来源的情况下
  3. 考虑使用更明确的变量赋值方式替代extract()
  4. 对于必须使用extract()的场景,确保对输入数组进行严格过滤

这个案例再次提醒我们,在涉及引用管理和对象生命周期时要格外小心,特别是在PHP这种具有复杂变量符号表和引用计数机制的语言中。

登录后查看全文
热门项目推荐

热门内容推荐

最新内容推荐

项目优选

收起
ohos_react_nativeohos_react_native
React Native鸿蒙化仓库
C++
176
262
RuoYi-Vue3RuoYi-Vue3
🎉 (RuoYi)官方仓库 基于SpringBoot,Spring Security,JWT,Vue3 & Vite、Element Plus 的前后端分离权限管理系统
Vue
863
511
ShopXO开源商城ShopXO开源商城
🔥🔥🔥ShopXO企业级免费开源商城系统,可视化DIY拖拽装修、包含PC、H5、多端小程序(微信+支付宝+百度+头条&抖音+QQ+快手)、APP、多仓库、多商户、多门店、IM客服、进销存,遵循MIT开源协议发布、基于ThinkPHP8框架研发
JavaScript
93
15
openGauss-serveropenGauss-server
openGauss kernel ~ openGauss is an open source relational database management system
C++
129
182
openHiTLSopenHiTLS
旨在打造算法先进、性能卓越、高效敏捷、安全可靠的密码套件,通过轻量级、可剪裁的软件技术架构满足各行业不同场景的多样化要求,让密码技术应用更简单,同时探索后量子等先进算法创新实践,构建密码前沿技术底座!
C
259
300
kernelkernel
deepin linux kernel
C
22
5
cherry-studiocherry-studio
🍒 Cherry Studio 是一款支持多个 LLM 提供商的桌面客户端
TypeScript
596
57
CangjieCommunityCangjieCommunity
为仓颉编程语言开发者打造活跃、开放、高质量的社区环境
Markdown
1.07 K
0
HarmonyOS-ExamplesHarmonyOS-Examples
本仓将收集和展示仓颉鸿蒙应用示例代码,欢迎大家投稿,在仓颉鸿蒙社区展现你的妙趣设计!
Cangjie
398
371
Cangjie-ExamplesCangjie-Examples
本仓将收集和展示高质量的仓颉示例代码,欢迎大家投稿,让全世界看到您的妙趣设计,也让更多人通过您的编码理解和喜爱仓颉语言。
Cangjie
332
1.08 K