压在透明的玻璃上c-国产精品国产一级A片精品免费-国产精品视频网-成人黄网站18秘 免费看|www.tcsft.com

CVE-2017-13253: 多個Android DRM服務(wù)中的緩沖區(qū)溢出

@tamir_zb最近披露了一個緩沖區(qū)溢出漏洞,影響到谷歌的多種Android DRM服務(wù)。 Google將其分類為高嚴重性,將其指定為CVE-2017-13253,并在3月份的安全更新中對其進行了修補。

在這篇博文中,我們將介紹該漏洞的詳細信息。 首先,我們將介紹相關(guān)的背景信息,從一般的Android機制到與漏洞相關(guān)的特定機制。 我們將重點介紹最近推出的Project Treble,以及它的變化究竟意味著什么。 然后,我們將分析這個漏洞及其影響。 我們將研究如何利用某些設(shè)備上的其他故障來解決此漏洞,以實現(xiàn)root權(quán)限。 最后,我們將討論該漏洞的起源以及它如何被阻止。 盡管Google聲稱Project Treble有利于安全性,但我們?nèi)詫⒖吹剿姆疵妗?/span>

Android的Binder和安全

在許多操作系統(tǒng)(包括Android)中使用的一種非常常見的安全模型圍繞進程間通信(IPC)展開。 在非特權(quán)進程中運行的不可信代碼可以與特權(quán)進程(服務(wù))進行通信,并要求它們執(zhí)行操作系統(tǒng)允許的特定操作。 該模型依賴于服務(wù)(和IPC機制本身)來正確驗證從非特權(quán)進程發(fā)送的每個輸入。 反過來,這意味著這些服務(wù)中的錯誤,尤其是輸入驗證部分中的錯誤很容易導(dǎo)致漏洞。

例如,Rani Idan在Zimperium發(fā)現(xiàn)的最新iOS漏洞依賴于這種方法。 IPC輸入驗證中的錯誤允許攻擊者從非特權(quán)應(yīng)用程序執(zhí)行具有更高權(quán)限的代碼。

在Android的情況下,IPC機制被稱為Binder。 Android Binder服務(wù)的安全性對于漏洞研究來說當然非常有趣。 Binder具有許多有用的功能,例如,它允許進程在彼此之間傳輸復(fù)雜對象,例如文件描述符或?qū)ζ渌鸅inder服務(wù)的引用。 為了保持簡單性和良好性能,Binder將每個事務(wù)限制為1MB的最大大小。 在進程需要傳輸大量數(shù)據(jù)的情況下,他們可以使用共享內(nèi)存來快速共享數(shù)據(jù)。

Binder’s C++ 目錄

Android的Binder庫(libbinder)為依賴于Binder的C ++代碼提供了許多抽象。 它允許你調(diào)用C ++類的遠程實例的方法,就好像它們不駐留在另一個進程中一樣。

每個使用這種機制的對象都在預(yù)定義的結(jié)構(gòu)中實現(xiàn)了幾個類:

  • 一個接口類,它定義了可以通過Binder調(diào)用的對象的方法。 以“I”為前綴。
  • 負責序列化輸入和反序列化輸出的“客戶端”類。 以“Bp”為前綴。
  • 負責反序列化輸入和序列化輸出的“服務(wù)器端”類。 前綴為“Bn”。

最終,在使用該對象時,幾乎總是使用接口類型。 這允許您以相同的方式處理對象,無論它處于同一個進程還是處于不同的進程中。

在ICrypto接口中使用libbinder的示例

代碼中的“服務(wù)器端”部分傳統(tǒng)上位于特權(quán)服務(wù)內(nèi)部(盡管在某些情況下角色是相反的),所以它通常負責驗證輸入。 驗證代碼可以從Bn *類開始,并沿著隨后調(diào)用的方法繼續(xù)。 這顯然是脆弱性研究中最有趣的部分。

ICrypto接口和解密方法

一般來說,在介紹Binder之后,我們來看看與漏洞相關(guān)的具體實現(xiàn)。 mediadrmserver服務(wù)(毫無疑問,負責DRM媒體)提供了一個加密對象的接口,接口名為ICrypto。 請注意,該對象最近更改為CryptoHal,我們將在稍后討論。 此接口的一般用途是允許非特權(quán)應(yīng)用程序解密需要較高權(quán)限解密的DRM數(shù)據(jù),如訪問TEE。 加密本身的細節(jié)不在本篇博文的范圍之內(nèi),再一次,我們對輸入驗證更感興趣。

ICrypto有多種方法,但無疑最重要的方法是解密。

解密的簽名(來源)

解密簽名中最引人注目的事情之一是輸入的復(fù)雜程度。 從我們的角度來看,這非常有趣。 復(fù)雜的輸入會導(dǎo)致復(fù)雜的驗證代碼(每個參數(shù)都通過Binder進行傳輸并且需要驗證),這些代碼可能易受漏洞影響。

我們來看看一些參數(shù):

參數(shù) 描述
模式 一個控制加密模式的枚舉。 其中一種模式是kMode_Unencrypted,它表示數(shù)據(jù)實際上未加密。 這種模式意味著數(shù)據(jù)只能從一個地方復(fù)制到另一個地方,而不涉及任何解密。 這使得這個過程更加簡單,所以從現(xiàn)在開始我們將專注于這個模式。 這也是我們不考慮一些加密相關(guān)參數(shù)(如密鑰或IV)的原因。
來源/目的地 輸入和輸出緩沖區(qū)。 由于數(shù)據(jù)的大小可能非常大(大于1MB),實際數(shù)據(jù)通過這些對象所代表的共享內(nèi)存進行傳輸。
offset 偏移到數(shù)據(jù)開始的輸入緩沖區(qū)。
附屬樣本 子樣本數(shù)組,是有關(guān)輸入的元數(shù)據(jù)。 每個子采樣表示多個清零字節(jié),后面跟著一些加密字節(jié)。 這使您可以在清除和加密的輸入數(shù)據(jù)之間切換。 使用kMode_Unencrypted也簡化了這一點,因為您只需使用一個代表所有清除數(shù)據(jù)的子樣本。

(有關(guān)API的更高級別Java一些參數(shù)的更多信息,請參閱MediaCodec.CryptoInfo)

現(xiàn)在讓我們仔細看看源和目標參數(shù)的類型:

(源)

這里的相關(guān)結(jié)構(gòu)成員是mHeapSeqNum和兩個mSharedMemory成員(DestinationBuffer的其余部分是在目標未被存儲為共享內(nèi)存的情況下,這種情況與此漏洞無關(guān))。 名稱堆在這里用來指代實際的共享內(nèi)存(這是你運行mmap的內(nèi)容)。 mHeapSeqNum是一個像這樣的內(nèi)存標識符,它以前使用稱為setHeap的ICrypto方法共享。 這兩個mSharedMemory成員僅表示堆內(nèi)緩沖區(qū)的偏移量和大小。 這意味著雖然mHeapSeqNum在源結(jié)構(gòu)內(nèi)部,但它實際上與兩者都相關(guān)。

清除數(shù)據(jù)解密運行的參數(shù)示例

值得注意的是,參數(shù)結(jié)構(gòu)的某些部分有點奇怪。 mSharedMemory是一個IMemory,它實際上連接到它自己的堆,并且應(yīng)該表示內(nèi)部的一個緩沖區(qū),但是這個堆被忽略,偏移量和大小被用于mHeapSeqNum堆。 源結(jié)構(gòu)中還存在mHeapSeqNum,但它與源和目標都有關(guān)。 這是所有這些代碼最近發(fā)生的變化的結(jié)果,這些代碼是作為名為Project Treble的Android框架的重要架構(gòu)的一部分而創(chuàng)建的。

Treble項目

Project Treble是作為Android 8.0的一部分引入的; 其主要目標是通過在AOSP和供應(yīng)商之間建立明確的分離來使系統(tǒng)更新更容易。 谷歌還聲稱,Project Treble通過增加更多的隔離功能來使Android安全性受益。

對于像mediadrmserver這樣的服務(wù),Project Treble意味著分離成多個進程。 負責解密的代碼屬于供應(yīng)商,因此它被分成多個供應(yīng)商進程,稱為HAL,每個供應(yīng)商都負責其自己的DRM方案。 mediadrm服務(wù)器的作用現(xiàn)在減少到在相關(guān)DRM方案的應(yīng)用程序和HAL進程之間傳輸數(shù)據(jù)。 mediadrmserver和HAL之間的通信也在Binder之上,但是在不同的域中并使用不同庫的格式 – libhwbinder。 之前提到的從Crypto到CryptoHal的變化是因為現(xiàn)在它是一個不同的類,其唯一目的是將數(shù)據(jù)轉(zhuǎn)換為libhwbinder的格式并將其傳遞給HAL。

上圖顯示了Google為什么聲稱Project Treble受益于安全。 權(quán)限在不同的進程中分開(每個HAL只能與自己的驅(qū)動程序通信),不受信任的應(yīng)用程序不再直接與高權(quán)限進程交互。

請注意,從Android 8.1開始,分離仍然是可選的,取決于供應(yīng)商。 例如,在Nexus 5X中,HAL都位于mediadrmserver進程中。 數(shù)據(jù)仍然轉(zhuǎn)換為HAL格式,但不會轉(zhuǎn)移到其他進程。

加密插件

我之前提到了不同的DRM方案,在Android術(shù)語中,每種DRM方案的處理程序都稱為插件,或者在我們的特定情況下稱為加密插件。 供應(yīng)商負責提供這些插件,但AOSP中有一些供銷售商使用的有用代碼。 例如,AOSP包含ClearKey DRM方案插件的完整開源實現(xiàn)。 通常,設(shè)備將具有開源的ClearKey插件和閉源的Widevine插件(例如Nexus / Pixel設(shè)備就是這種情況)。

上述Project Treble變化的問題是現(xiàn)在插件接收HAL格式的數(shù)據(jù)。 為了簡化轉(zhuǎn)換,無需更新每個插件以支持這種新格式,默認的Crypto Plugin實現(xiàn)已添加到AOSP供供應(yīng)商使用。 該實現(xiàn)將數(shù)據(jù)從HAL格式轉(zhuǎn)換為傳統(tǒng)格式,并將其傳遞給原始插件代碼。 理想情況下,這個解決方案應(yīng)該只是暫時的,直到插件更新,否則我們會留下冗余格式轉(zhuǎn)換(往返于HAL)。

數(shù)據(jù)格式轉(zhuǎn)換的流程

研究源代碼

在介紹ICrypto的解密方法的一般過程之后,我們來仔細看看共享內(nèi)存緩沖區(qū)的驗證代碼。 正如您可能已經(jīng)猜到的(因為我們正在談?wù)摼彌_區(qū)溢出),這是發(fā)現(xiàn)漏洞的地方。

如前所述,驗證通常從Bn *類開始,在我們的例子中就是ICrypto接口的“服務(wù)器端”BnCrypto。

BnCrypto驗證代碼的一部分(源)

  • 首先,代碼檢查子采樣大小的總和是否有效并且不會溢出。 請記住,這是要復(fù)制的數(shù)據(jù)的大小。
  • 它還檢查這個總和是否與totalSize匹配,通過Binder傳遞的另一個參數(shù)非常多余(您可以通過子樣本的總和來告訴總大小,代碼明確驗證了這種情況)。
  • 接下來的檢查是數(shù)據(jù)大小不超過源緩沖區(qū)的大小。
  • 最后,它檢查數(shù)據(jù)大小加上偏移量仍然不超過源緩沖區(qū)。

Crypto Hal將數(shù)據(jù)轉(zhuǎn)換為HAL格式并將其發(fā)送給相關(guān)插件; 這里沒有有趣的驗證代碼。

接下來,默認的Crypto Plugin實現(xiàn)(可能會或可能不在不同的進程中)將數(shù)據(jù)轉(zhuǎn)換回傳統(tǒng)格式并繼續(xù)驗證它。

部分默認加密插件驗證碼(源)

關(guān)于這個代碼的一個附注:我覺得它有點混亂。 有多個“dest”和“source”變量,sourceBase和destBase實際上是完全相同的東西(堆),并且根本沒有任何評論可以幫助你。 正如我之前提到的那樣,這部分是全新的,并且僅在Android 8.0中添加,因此它是有道理的。 盡管如此,我還是懷疑這種混亂導(dǎo)致了這個漏洞,因為它使得查看整個驗證代碼和查看是否有缺失更加困難。

  • 這里的第一個檢查是偏移量和緩沖區(qū)大小的總和不超過堆大小。 sourceBase是堆,而源是之前的source.mSharedMemory。 如果您對兩個偏移量感到困惑,請記住mSharedMemory包含一個偏移量,并且解密方法也有一個不同的偏移量參數(shù)。
  • 其他檢查類似,但在目標緩沖區(qū)上執(zhí)行。 destBuffer是destination.mSharedMemory和destBase與sourceBase相同的堆。 這次不涉及偏移量參數(shù)。

最終,每個緩沖區(qū)都簡化為一個指向內(nèi)存的指針; 偏移量現(xiàn)在是指針的一部分,而緩沖區(qū)大小被省略。 為了確定數(shù)據(jù)大小,插件使用subSamples數(shù)組。

數(shù)據(jù)未加密時的ClearKey插件代碼(源代碼)

上面的代碼顯示了最后一部分,以幫助理解流程。 如前所述,當數(shù)據(jù)未加密時,它只是從一個地方復(fù)制到另一個地方。

到目前為止,我已經(jīng)提供了足夠的信息,可以在理論上發(fā)現(xiàn)漏洞。 如果你想嘗試做到這一點,歡迎回去繼續(xù)閱讀代碼。 根據(jù)我的經(jīng)驗,在這類博客文章中很難提供足夠的信息來發(fā)現(xiàn)它,同時仍然保持實際的挑戰(zhàn)性(尤其是從已經(jīng)找到它的人的角度來看),所以即使你 無法發(fā)現(xiàn)它(或者它可能太簡單了?)。

該漏洞

問題是沒有驗證被復(fù)制的數(shù)據(jù)量沒有超過目標緩沖區(qū)。 對源緩沖區(qū)只有一個類似的檢查(BnCrypto的第三個檢查檢查并且下一個檢查甚至將額外的偏移量考慮在內(nèi))。 與目標緩沖區(qū)相關(guān)的唯一檢查是默認Crypto Plugin的第二次檢查(它確保緩沖區(qū)位于堆內(nèi)并且不超過它),但這僅僅是不夠的。

我們來看一個例子。 假設(shè)要復(fù)制的數(shù)據(jù)的大小是0x1000。 由于這個大小是由subsamples數(shù)組表示的,所以我們將在該數(shù)組中有一個條目,其中包含0x1000個清晰字節(jié)(以及0個加密字節(jié))。 堆也將有0x1000字節(jié),并且源緩沖區(qū)將指向整個堆(偏移量= 0,大小= 0x1000)。 目標緩沖區(qū)是它變得有趣的地方。 假設(shè)偏移量是0x800,大小是0x800。 這仍然適合堆,所以它通過了默認加密插件的檢查。 在這種情況下,會出現(xiàn)溢出; 0x800字節(jié)將在堆后寫入。

概念驗證

觸發(fā)漏洞的示例的代碼

注意:MemoryBase對象是IMemory libbinder接口的實現(xiàn)。 這是一個使用Binder將引用傳遞給其他Binder對象的例子。 這也是Binder角色顛倒的一個例子。 特權(quán)流程是“客戶端”,因此它通過Binder請求信息并負責驗證它。

漏洞的影響

此漏洞允許攻擊者用任意數(shù)據(jù)覆蓋目標進程中的內(nèi)存。 由于這是內(nèi)存頁級別的溢出,因此目前沒有任何緩解措施可以阻止它(例如堆棧溢出堆棧)。 由于缺省Crypto Plugin的檢查,數(shù)據(jù)必須從共享內(nèi)存開始,這仍然受到限制。 這意味著只有位于共享內(nèi)存之后的內(nèi)存才能被覆蓋。 此外,內(nèi)存中的許多區(qū)域通常是未分配或不可寫入的,因此試圖在其中寫入將導(dǎo)致分段錯誤。

受影響的流程取決于供應(yīng)商的實施。 如果供應(yīng)商不將HAL分成不同的進程,則mediadrmserver會受到影響。 如果供應(yīng)商將它們分開,那么Crypto Plugin的每個HAL服務(wù)都會受到影響。 由于默認的Crypto Plugin代碼僅留下指向目標緩沖區(qū)的指針,并且大小僅由子采樣確定,供應(yīng)商代碼無法確定它接收到格式錯誤的數(shù)據(jù)。 這意味著供應(yīng)商部分編寫得并不重要,它仍然是脆弱的(理論上,供應(yīng)商可能會忽略AOSP的默認加密插件代碼,并實現(xiàn)自己的代碼來檢測格式錯誤的數(shù)據(jù),但我沒有’ 沒有看到供應(yīng)商那么做)。

可能的影響

假設(shè)攻擊者設(shè)法利用此漏洞將特權(quán)提升為易受攻擊服務(wù)的特權(quán),那么我們來看看他們可以實現(xiàn)的功能。 請注意,這部分大多是推測性的。 我沒有編寫漏洞利用表,但是我對這個漏洞理論上如何被用來達到完全的root權(quán)限有一些想法。

這就是Android的SELinux規(guī)則發(fā)揮作用的地方; 即使易受攻擊的服務(wù)擁有更多權(quán)限,SELinux仍然會嚴重限制它們。 盡管如此,即使在限制之后,我們?nèi)匀涣粝铝艘粋€非常有趣的權(quán)限:完全訪問TEE設(shè)備。

在這種情況下,Project Treble的額外隔離幾乎沒有幫助。 易受攻擊的進程將是可以訪問TEE設(shè)備的進程,無論是否存在分離到多個進程。 在分離的情況下,唯一受保護的過程是中間沒有趣味的媒體服務(wù)器。

那么你可以通過完全訪問TEE來做什么? Gal Beniamini的優(yōu)秀研究表明,許多設(shè)備無法正確吊銷舊的易受攻擊的TEE信托。 這意味著,如果您攻擊具有舊的易受攻擊的trustlet的設(shè)備,則可以使用TEE設(shè)備的訪問權(quán)限,加載trustlet并將其用于TEE上的代碼執(zhí)行。 更重要的是,Gal Benimaini過去也展示了基于Qualcomm的設(shè)備上的TEE代碼執(zhí)行如何導(dǎo)致root權(quán)限。

可能的攻擊流向根特權(quán)

漏洞的來源

我已經(jīng)多次提到Project Treble如何對代碼的這個區(qū)域進行重大修改。 如果知道這些更改實際上引入了此漏洞(在更改之前,目標緩沖區(qū)甚至無法以此格式設(shè)置),那么您可能不會感到驚訝。

顯然,你不能僅僅因為使代碼易受攻擊而對其進行重構(gòu),因為這意味著代碼重構(gòu)不應(yīng)該發(fā)生,這是不正確的。 正如我已經(jīng)指出的那樣,這段代碼的多個部分都是混亂的或冗余的。 雖然這本身并不一定會使代碼易受攻擊,但確實增加了這種可能性,因為它使代碼更難以復(fù)審(代碼的某些部分花了我相當長的時間才能理解,而相比之下它們實際上的復(fù)雜性 做)。 因此,雖然漏洞有時難以發(fā)現(xiàn),但通常更容易發(fā)現(xiàn)雜亂或冗余的代碼。 我知道從評論者的角度來看批評不好的代碼設(shè)計比實際編寫好的代碼更容易,但我仍然認為應(yīng)該改進一些部分。

結(jié)論

Google聲稱Project Treble對Android的安全性有好處,但在這個例子中,它卻反其道而行之。 高音項目本身并不一定是壞的,這里的關(guān)鍵問題是實施處理得不好。

可以在GitHub(https://github.com/tamirzb/CVE-2017-13253)上找到觸發(fā)漏洞的PoC的完整源代碼以及一些額外信息。

原文:https://blog.zimperium.com/cve-2017-13253-buffer-overflow-multiple-android-drm-services/

上一篇:MySQL UDF開發(fā)

下一篇:如何在未Root的Android設(shè)備上解密數(shù)據(jù)庫

站长统计