您好,登錄后才能下訂單哦!
今天就跟大家聊聊有關如何進行Safari信息泄露漏洞的分析,可能很多人都不太了解,為了讓大家更加了解,小編給大家總結了以下內容,希望大家根據這篇文章可以有所收獲。
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。
看完上述內容,你們對如何進行Safari信息泄露漏洞的分析有進一步的了解嗎?如果還想了解更多知識或者相關內容,請關注億速云行業資訊頻道,感謝大家的支持。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。