Safari信息泄露漏洞分析
字数 1350 2025-08-18 11:37:42
Safari JavaScriptCore 数组拼接漏洞分析 (CVE-2018-4358)
漏洞概述
本教学文档详细分析 Safari 浏览器 JavaScriptCore 引擎中存在的数组拼接漏洞 (CVE-2018-4358),该漏洞源于 Array.prototype.concat 方法的实现缺陷,可能导致信息泄露。
背景知识
JavaScriptCore 数组优化机制
JavaScriptCore (JSC) 是 WebKit 中的 JavaScript 引擎,对数组对象进行了多种优化:
- IndexingType:8位整数表示的标志组合,定义于 IndexingType.h
- 数组类型优化:
ArrayWithUndecided:所有元素均为 undefined,未存储实际值ArrayWithDouble:包含双精度浮点数的数组- 引擎根据 indexing 类型选择快速路径处理
Butterfly 概念
Butterfly 是 JavaScriptCore 中用于存储数组元素的数据结构,是引擎内部实现的关键部分。
漏洞分析
问题代码位置
漏洞存在于 ArrayPrototype.cpp 中的 arrayProtoPrivateFuncConcatMemcpy 函数实现。
关键问题点
-
数组类型合并逻辑 (
mergeIndexingTypeForCopying函数):- 当第一个数组类型为
ArrayWithUndecided时,直接返回第二个数组的类型 - 未验证第二个数组是否已正确初始化
- 当第一个数组类型为
-
内存拷贝操作:
if (type == ArrayWithDouble) { double* buffer = result->butterfly()->contiguousDouble().data(); memcpy(buffer, firstButterfly->contiguousDouble().data(), sizeof(JSValue) * firstArraySize); memcpy(buffer + firstArraySize, secondButterfly->contiguousDouble().data(), sizeof(JSValue) * secondArraySize); }- 当第一个数组为
ArrayWithUndecided时,其 butterfly 可能未初始化 - 直接进行 memcpy 会导致未初始化内存被拷贝
- 当第一个数组为
-
未初始化数组创建:
NewArrayWithSizeDFG JIT 操作码可创建未初始化数组- FTL (Faster Than Light) JIT 中的
allocateJSArray函数:if (hasUndecided(rawIndexingType)) return; // 跳过初始化
漏洞利用
利用条件
- 创建一个
ArrayWithUndecided类型的未初始化数组 - 将其与
ArrayWithDouble类型数组拼接
利用步骤
-
触发 JIT 编译:
- 重复调用创建数组并拼接的函数,使 FTL 编译器对其进行优化
-
内存喷射:
- 在堆上布置目标对象
- 通过漏洞泄漏未初始化内存中的对象地址
-
信息泄露:
- 从返回的数组中提取内存地址信息
修复方案
该漏洞已在以下版本中修复:
- iOS 12 最新版本
- macOS Mojave 最新版本 (Safari)
修复方法应包括:
- 在
mergeIndexingTypeForCopying中添加初始化状态检查 - 确保
ArrayWithUndecided数组在拼接前被正确初始化
防御建议
- 及时更新浏览器至最新版本
- 对 JavaScript 引擎中的数组操作进行严格的边界和状态检查
- 在敏感操作前验证数组初始化状态
总结
此漏洞展示了 JavaScript 引擎优化机制可能引入的安全问题,特别是在处理特殊数组类型时的边界条件。理解这类漏洞有助于开发者更好地编写安全代码和安全研究人员发现类似问题。