Safari信息泄露漏洞分析

2018 年 11 月 3 日 FreeBuf

前言

Javascript中的数组和数组对象一直都是编程人员优化的主要目标,一般来说,数组只会包含一些基本类型数据,比如说32位整数或字符等等。因此,每个引擎都会对这些对象进行某些优化,并提升不同元素类型的访问速度和密集型表示。

在JavaScriptCore中,JavaScript引擎是在WebKit中实现的,其中每一个存储在对象中的元素都代表着一个IndexingType值,一个8位整数代表一套Flag组合,具体的参数定义可以在IndexingType.h中找到。接下来,引擎会检测一个对象中indexing的类型,然后决定使用哪一条快速路径,其中最重要的一种indexing类型就是ArrayWithUndecided,它表示的是所有元素均为未定义(undefined),而且没有存储任何实际的值。在这种情况下,引擎为了提升性能,会让这些元素保持未初始化。

分析

下面,我们一起看一看旧版本中实现Array.prototype.concat的代码(ArrayPrototype.cpp):

EncodedJSValueJSC_HOST_CALL arrayProtoPrivateFuncConcatMemcpy(ExecState* exec){    ...     unsigned resultSize =checkedResultSize.unsafeGet();    IndexingType firstType =firstArray->indexingType();    IndexingType secondType =secondArray->indexingType();    IndexingType type =firstArray->mergeIndexingTypeForCopying(secondType); // [[ 1 ]]    if (type == NonArray ||!firstArray->canFastCopy(vm, secondArray) || resultSize >=MIN_SPARSE_ARRAY_INDEX) {        ...    }     JSGlobalObject* lexicalGlobalObject =exec->lexicalGlobalObject();    Structure* resultStructure =lexicalGlobalObject->arrayStructureForIndexingTypeDuringAllocation(type);    if(UNLIKELY(hasAnyArrayStorage(resultStructure->indexingType())))        return JSValue::encode(jsNull());    ASSERT(!lexicalGlobalObject->isHavingABadTime());    ObjectInitializationScopeinitializationScope(vm);    JSArray* result =JSArray::tryCreateUninitializedRestricted(initializationScope, resultStructure,resultSize);    if (UNLIKELY(!result)) {        throwOutOfMemoryError(exec, scope);        return encodedJSValue();    }     if (type == ArrayWithDouble) {        [[ 2 ]]        double* buffer =result->butterfly()->contiguousDouble().data();        memcpy(buffer,firstButterfly->contiguousDouble().data(), sizeof(JSValue) *firstArraySize);        memcpy(buffer + firstArraySize,secondButterfly->contiguousDouble().data(), sizeof(JSValue) *secondArraySize);    } else if (type != ArrayWithUndecided) { ...

这个函数主要用来判断结果数组[[1]]的indexing类型,我们可以看到,如果indexing类型为ArrayWithDouble,它将会选择[[2]]作为快速路径。接下来,我们看一看:

mergeIndexingTypeForCopying的实现代码,这个函数主要负责在Array.prototype.concat被调用时,判断结果数组的indexing类型:

inlineIndexingType JSArray::mergeIndexingTypeForCopying(IndexingType other){    IndexingType type = indexingType();    if (!(type & IsArray && other& IsArray))        return NonArray;     if (hasAnyArrayStorage(type) ||hasAnyArrayStorage(other))        return NonArray;     if (type == ArrayWithUndecided)        return other; [[ 3 ]] ...

我们可以看到在这种情况下,有一个输入数组的indexing类型为ArrayWithUndecided,结果indexing类型将会是另一个数组的indexing类型。因此,如果我们我们用一个indexing类型为ArrayWithUndecided的数组和另一个indexing类型为ArrayWithDouble的数组去调用Array.prototype.concat方法的话,我们将会按照快速路径[[2]]运行,并将两个数组进行拼接。

这段代码并不能保证这两个“butterfly”(JavaScript引擎攻击技术里的一种概念,详情请参考【这篇文章】)在代码调用memcpy之前能够正确初始化。这也就意味着,如果我们能够找到一条允许我们创建一个未初始化数组并将其传递给Array.prototype.concat的代码路径,那我们就能够在堆内存中拥有一个包含了未初始化值的数组对象了,而且它的indexing类型还不是ArrayWithUndecided。从某种程度上来说,这个安全问题跟lokihardt在2017年报告的一个旧漏洞有些相似,只不过利用方式不同。

在创建这种数组对象时,可以利用NewArrayWithSize DFG JIT的操作码来实现,在对FTLLowerDFGToB3.cpp中FTL所实现的allocateJSArray操作码进行分析之后,我们可以看到这个数组将会包含未初始化的值。引擎根本不需要对数组进行初始化,因为这个数组的indexing类型为ArrayWithUndecided。

ArrayValuesallocateJSArray(LValue publicLength, LValue vectorLength, LValue structure,LValue indexingType, bool shouldInitializeElements = true, boolshouldLargeArraySizeCreateArrayStorage = true){    [ ... ]    initializeArrayElements(       indexingType,       shouldInitializeElements ?m_out.int32Zero : publicLength, vectorLength,       butterfly); ...voidinitializeArrayElements(LValue indexingType, LValue begin, LValue end, LValuebutterfly){     if (begin == end)        return;     if (indexingType->hasInt32()) {        IndexingType rawIndexingType =static_cast<IndexingType>(indexingType->asInt32());        if (hasUndecided(rawIndexingType))            return;  // [[ 4 ]]

语句new Array(n)在被FTL JIT编译时将会触发[[4]],然后返回一个indexing类型为ArrayWithUndecided的数组,其中就包含未初始化的元素。

漏洞利用

清楚了之前所介绍的漏洞原理之后,想必触发这个漏洞也并非难事:我们可以不断重复调用一个使用new Array()方法来创建数组的函数,然后调用concat方法将这个数组和一个只包含double类型数据的数组进行拼接。在调用够足够次数之后,FTL编译器将会对其进行编译。

这份【漏洞利用代码】可以利用这个漏洞来泄漏一个目标对象的内存地址,实现机制是通过我们所创建的对象进行内存喷射,在触发这个漏洞之后,我们就能够从代码所返回的数组中找到目标对象的地址了。

总结

这个漏洞目前已经在iOS 12和macOS Mojave的最新版本(Safari)中修复了,该漏洞的CVE编号为CVE-2018-4358。

* 参考来源:phoenhex,FB小编Alpha_h4ck编译,转载请注明来自FreeBuf.COM

登录查看更多
0

相关内容

Safari 是苹果公司所开发的网页浏览器,并自带于 Mac OS X。Safari 在 2003 年 1 月 7 日首度发布测试版,并成为 Mac OS X v10.3 与之后的默认浏览器,也是iOS的指定浏览器。Windows 版本的首个测试版在 2007 年 6 月 11 日推出,支持 Windows XP,Windows Vista 和 Windows 7,在 2008 年 3 月 18 日推出正式版。2012 年 7 月 27 日 Apple 已经停止开发 Windows 版的 Safari 浏览器。 Source: 维基百科,自由的百科全书 | Safari
异质信息网络分析与应用综述,软件学报-北京邮电大学
【复旦大学-SP2020】NLP语言模型隐私泄漏风险
专知会员服务
24+阅读 · 2020年4月20日
【图神经网络(GNN)结构化数据分析】
专知会员服务
115+阅读 · 2020年3月22日
【新书】Java企业微服务,Enterprise Java Microservices,272页pdf
新时期我国信息技术产业的发展
专知会员服务
69+阅读 · 2020年1月18日
知识神经元网络 KNN(简介),12页pdf
专知会员服务
14+阅读 · 2019年12月25日
【干货】大数据入门指南:Hadoop、Hive、Spark、 Storm等
专知会员服务
95+阅读 · 2019年12月4日
后渗透利用msf关闭防火墙
黑白之道
8+阅读 · 2019年8月24日
Linux挖矿病毒的清除与分析
FreeBuf
14+阅读 · 2019年4月15日
Ray RLlib: Scalable 降龙十八掌
CreateAMind
9+阅读 · 2018年12月28日
实战 | 用Python做图像处理(三)
七月在线实验室
15+阅读 · 2018年5月29日
机器学习(26)之K-Means实战与调优详解
机器学习算法与Python学习
4+阅读 · 2017年11月19日
[软件方法]涉众利益和基本路径
UMLChina
4+阅读 · 2017年9月2日
python进行数据分析之数据聚合和分组运算
Python技术博文
3+阅读 · 2017年8月21日
【宁波站】网络爬虫与文本挖掘
数萃大数据
5+阅读 · 2017年7月19日
Arxiv
35+阅读 · 2019年11月7日
Video-to-Video Synthesis
Arxiv
9+阅读 · 2018年8月20日
Arxiv
3+阅读 · 2012年11月20日
VIP会员
相关VIP内容
异质信息网络分析与应用综述,软件学报-北京邮电大学
【复旦大学-SP2020】NLP语言模型隐私泄漏风险
专知会员服务
24+阅读 · 2020年4月20日
【图神经网络(GNN)结构化数据分析】
专知会员服务
115+阅读 · 2020年3月22日
【新书】Java企业微服务,Enterprise Java Microservices,272页pdf
新时期我国信息技术产业的发展
专知会员服务
69+阅读 · 2020年1月18日
知识神经元网络 KNN(简介),12页pdf
专知会员服务
14+阅读 · 2019年12月25日
【干货】大数据入门指南:Hadoop、Hive、Spark、 Storm等
专知会员服务
95+阅读 · 2019年12月4日
相关资讯
后渗透利用msf关闭防火墙
黑白之道
8+阅读 · 2019年8月24日
Linux挖矿病毒的清除与分析
FreeBuf
14+阅读 · 2019年4月15日
Ray RLlib: Scalable 降龙十八掌
CreateAMind
9+阅读 · 2018年12月28日
实战 | 用Python做图像处理(三)
七月在线实验室
15+阅读 · 2018年5月29日
机器学习(26)之K-Means实战与调优详解
机器学习算法与Python学习
4+阅读 · 2017年11月19日
[软件方法]涉众利益和基本路径
UMLChina
4+阅读 · 2017年9月2日
python进行数据分析之数据聚合和分组运算
Python技术博文
3+阅读 · 2017年8月21日
【宁波站】网络爬虫与文本挖掘
数萃大数据
5+阅读 · 2017年7月19日
相关论文
Top
微信扫码咨询专知VIP会员