Android FBE的背景我們將在本文介紹分析靜態數據加密。 Android FBE是Android Full Disk Encryption的簡稱,是一種安全機制,用於對Android設備的所有數據進行加密,保護用戶的個人隱私和敏感數據。
簡而言之,此功能允許永遠不以明文形式存儲文件,以防止攻擊者通過簡單地提取存儲設備來讀取它們。相反,文件在加載到內存中時(例如,通過文本編輯器)會自動解密,並在寫回磁盤時再次加密。這要歸功於操作系統的支持,Android歷來使用兩種方法:全磁盤加密(FDE)和基於文件的加密(FBE)。顧名思義,基於文件的加密在文件級工作。也就是說,每個文件都有自己的密鑰,並且可以獨立於其他文件進行解密。 Android依賴於Linux內核特性fscrypt來實現這一點,該特性在Ext4和F2FS等各種文件系統中都得到支持。在為目錄樹獲得主密鑰之後,系統將為文件、目錄和符號鏈接檢索單獨的密鑰。
由於採用了文件級方法,FBE實現非常精確。 Android利用這一點將文件劃分為兩個加密級:
設備加密(DE):文件在啟動後立即可用;
憑證加密(CE):文件只有在用戶進行身份驗證後才可用(這是用戶數據的選擇級別)。
在啟動設備時自動派生DE密鑰,考慮到這一點以及它所保護的數據類型,從攻擊者的角度來看,它並不是特別有趣。然而,值得注意的是,這是直接啟動功能的基礎,允許在用戶進行身份驗證之前解鎖設備的某些功能,比如警報。
儘管如此,由於攻擊者的目標可能是檢索私有數據,因此本文主要關注CE密鑰。派生它的步驟相當複雜,過程從系統擁有的一些DE保護文件(在/data/system_DE//spblob中)開始。最終密鑰的原始字節實際上是從憑證的原始字節派生出來的。儘管過程複雜,但這意味著無論攻擊者可以利用多少漏洞,他們仍然需要暴力破解憑證以將其提供給密鑰派生過程。
使用TrustZone派生CE密鑰
上圖顯示了派生CE密鑰所需的不同組件是如何鏈接在一起的。如上所述,這是一個相當複雜的過程,所以我們建議在一個單獨的選項卡中打開圖片。對於沒有配備安全芯片的設備,密鑰派生來自兩個不同的受保護組件:
特權用戶(system或root)擁有的文件:普通用戶無法訪問;
TEE保護密鑰:這些密鑰只能在TEE內部由Keymaster應用程序使用。這些密鑰也是與身份驗證綁定的,因此只有在用戶成功通過身份驗證時才能使用它們。
這意味著攻擊者應該能夠提升權限並篡改可信執行環境,以便提取密鑰或能夠在身份驗證之前使用密鑰。為此,我們有必要了解Gatekeeper如何進行身份驗證。
使用Gatekeeper進行身份驗證
Gatekeeper是TEE中經常出現的可信應用程序(TA)之一,通過與相應的Android守護進程以及硬件抽象層通信,它在驗證用戶的身份驗證憑證方面發揮著關鍵作用。請注意,Gatekeeper僅通過PIN/密碼/模式參與身份驗證,而其他TA用於支持生物識別。儘管如此,當用戶在啟動設備時首次進行身份驗證時,他們無法使用生物識別技術,原因恰恰與數據加密有關。
Gatekeeper實現了兩個概念上簡單的命令:Enroll和Verify。通常在用戶首次設置身份驗證因素或更改身份驗證因素時調用Enroll。該命令接受一個所謂的密碼(pwd)blob,對其進行簽名,然後返回,將其轉換為密碼句柄。密碼blob是從憑證創建的,憑證首先使用scrypt進行擴展,然後與哈希字符串組合。用於簽名所提供的密碼的密鑰是Gatekeeper的內部密鑰,用於驗證憑證。這樣的功能是通過Verify命令實現的,而在用戶嘗試進行身份驗證時調用該命令。顧名思義,它驗證當前身份驗證嘗試的密碼blob是否有效。它通過計算其HMAC並將其與原始密碼句柄進行比較來實現這一點,原始密碼句柄也與命令一起發送。
Scrypt是一個密鑰派生函數,在這種情況下,它通過需要大量內存來減緩自定義硬件攻擊。它的參數與憑證的鹽值一起存儲在一個文件中。這意味著每次身份驗證嘗試的延遲可以忽略不計,但卻讓需要多次進行身份驗證的攻擊者減慢了速度。
如果身份驗證成功,Gatekeeper將創建一個身份驗證(auth)令牌。這是一個標準格式的簽名令牌(如AOSP中指定的),旨在防止重放攻擊。此令牌證明用戶已通過身份驗證,需要發送給Keymaster TA以解鎖綁定身份驗證的密鑰。如果身份驗證嘗試失敗,Gatekeeper的節流機制就會啟動,使暴力破解變得不可能。這是與實現相關的,但通常TA存儲有關每個失敗請求的時間的信息,並在此類失敗請求的頻率變得可疑時開始返回錯誤。當用戶再次成功進行身份驗證時,計數器將重置。
合成密碼用戶通過身份驗證後,系統就有了一個有效的applicationId。在真正成為CE密鑰之前,還需要經過幾個步驟。對我們來說,第一個也是更有趣的是合成密碼的推導過程。檢索到這些信息後,還有許多一些操作,但是這些步驟不需要用戶或某些受信任的組件提供任何信息。
合成密碼存儲在Android文件系統中,必須用兩個不同的密鑰解密。第一個是存儲在Android Keystore中的常規密鑰,該密鑰受TEE保護並綁定身份驗證。由於這些密鑰永遠不會離開TEE,因此它們以加密形式存儲,並且需要在Keymaster TA中進行解密。除此之外,如上所述,只有當命令還包含先前由Gatekeeper生成的驗證令牌並且仍然有效時,才能使用它們。一旦在TEE中完成了第一次解密,就使用哈希的applicationId作為密鑰再次解密中間緩衝區。注意,這裡的AES是使用GCM模式完成的,如果密鑰出現問題,則由於標記不匹配而導致操作失敗。
此時,攻擊者基本上需要完成三件事才能恢復CE密鑰。首先,他們需要能夠檢索特權用戶擁有的文件,這很可能是利用了一個包含多個漏洞的內核漏洞。然後,他們還必須篡改TEE,要么從Keymaster洩露所需的密鑰,要么攻擊Gatekeeper中的憑證驗證和認證令牌生成。最後,他們需要對獲得的信息執行暴力破解。
用於Gatekeeper的PoC研究人員在三星A22設備(更準確地說是在A226B和A225F)上實現了PoC,這些設備使用來自Mediatek 的兩個易受攻擊的SoC: MT6769V和MT6833V,可以使用MTKClient利用。該工具與下載模式(類似於高通soc上的EDL模式)交互,該模式暴露了一個USB接口,該接口最初用於在其上執行支持操作(例如刷新固件)。要觸發該漏洞,就必須物理訪問,並且在某些設備(如A225F)上,必須在設備PCB上短路兩個引腳才能進入下載模式。一旦設備以正確的模式啟動,該工具利用Boot ROM漏洞,然後修改BL2(在Mediatek 啟動模式中稱為preloader)以禁用下一個安全啟動檢查,最後將其加載到設備上並在其上啟動。
但要實現攻擊,就需要修復以下組件:
1.BL3,它被稱為小內核(簡稱為LK),禁用Android驗證啟動檢查,因為我們想要啟動修改的Android映像;
2.Android系統(在本示例中為啟動鏡像),授予我們root訪問權限,並修改供應商分區中存在的Gatekeeper Trusted應用程序;
3.TEE操作系統(稱為TEEGRIS)禁用對受信任應用程序的驗證。
獲得Android系統最高權限(AndroidRooting)
為了實現AndroidRooting,我們使用了Magisk。用修復的Gatekeeper TA替換它,我們只需要在SPU分區中創建一個新文件,然後Magisk的init程序在啟動時將其安裝在現有文件的位置。這種方法的優點是,它可以簡單地替換任何文件,因為我們只需要將它放在復制目錄樹的SPU分區中。
一旦完成,我們就可以對設備進行root訪問,然後使用它來訪問CE密鑰派生中涉及的文件。
修復TEEGRISTEEGRIS是三星設計的TrustZone操作系統,可以在Exynos和Mediatek 的soc上找到。它的設計和逆向工程已經被介紹了很多次,所以本文只關注我們需要修復的部分來實現我們的目標:執行修改後的TA。在本文的示例中,我們決定修復Gatekeeper,以繞過句柄驗證並始終生成有效的驗證令牌。
TEEGRIS分為幾個鏡像:
tee1.img:它包含Arm Trusted Firmware(在監視器模式下以最高權限執行-EL3)、Secure World內核和一個名為userboot.so的二進製文件。最後一個對我們來說非常重要,因為它用於加載和驗證TEEGRIS的根文件系統。
tzar.img:這是TEEGRIS的根文件系統,以逆向工程的自定義壓縮格式存儲。它包含可供其他庫使用但也可供TA使用的庫,以及二進製文件,其中包括一個名為root_task的二進製文件,負責驗證和運行Android提供的TA。
super.img:它是包含幾個邏輯分區的Android主分區。其中之一是供應商分區,包含大多數TA,包括Gatekeeper。
總而言之,我們需要修復userboot。所以二進制禁用驗證的TZAR。然後,我們修復root_task以禁用TA的驗證,這樣終於可以修復Gatekeeper了。
修復GatekeeperGatekeeper用於驗證用戶的憑證。驗證使用密鑰派生函數(KDF)生成一個惟一的值,然後可以將該值與作為參數傳遞的預期值進行比較。在Trusty TEE實現中,KDF實際上是一個使用內部密鑰的HMAC。對於TEEGRIS來說,KDF似乎是一個自定義的,顯然是在加密驅動程序中實現的,至少在基於exynos的設備上,它依賴於內部加密處理器。
如果憑證匹配,Gatekeeper生成一個auth_token並將其發送回Android,以便它可以附加到Keymaster請求。需要注意的是,這是Keymaster解密身份驗證綁定密鑰所必需的,例如加密的合成密碼。這裡有幾個選項,但我們決定修復兩個值之間的比較,以確保接受任何憑證。這是可能的,因為auth_token生成機制不使用憑證中的任何位。由於進行過修改,每次我們輸入一些憑證時,Gatekeeper都會生成令牌並返回成功,使系統相信它可以繼續下一步來解鎖設備。可以肯定的是,它不能用錯誤的憑證解密用戶數據。但是在嘗試之前,Keymaster任務必須執行合成密碼的第一次解密(它被加密了兩次)。
我們可以按照這個辦法盜取第一個AES解密操作的結果。該設備是根設備,使用Frida,我們可以在SyntheticPasswordCrypto.decryptBlob中暫停請求該操作的system_server進程。檢索到該值後,我們就可以開始強制使用憑據了。
暴力破解憑證暴力破解的代碼如下所示:
從設備加密的文件中檢索scrypt的參數。顧名思義,value_leaked_from_keymaster就是我們通過Frida盜取的值。由於此AES_Decrypt函數背後使用的GCM操作模式,如果密鑰是錯誤的,解密將失敗,我們知道我們需要選擇另一個密碼。如果成功,就意味著我們找到了正確的值。具體視頻請點此。
就性能而言,暴力執行腳本肯定可以改進。如上所述,即使只是簡單地將它移動到一個一般功能的VM上,也有顯著的改進。使用專用硬件會有所不同,但這不是我們PoC的重點,我們更願意把重點放在實現暴力執行所需的過程上。
利用安全芯片派生CE密鑰
上圖顯示了使用安全芯片時如何派生CE密鑰。該模式與上一部分中介紹的模式非常相似,主要區別在於引入了一個名為Weaver的新組件,並用於生成applicationId。
使用Weaver進行身份驗證Weaver是一個依賴於安全芯片來存儲密鑰和值的服務,每個值被分配到一個唯一的插槽。它公開了一個由三個命令組成的非常簡單的API:
Read:在輸入中提供插槽編號和密鑰,如果密鑰正確,則接收相關值;
write:提供要存儲的插槽編號、密鑰和值;
getConfig:檢索Weaver實現的配置信息。
與Gatekeeper類似,Weaver實現了一種節流機制,該機制在多次讀取嘗試失敗後生效。
當安全芯片可用時,使用scrypt生成的令牌將轉換為Weaver密鑰,然後將該密鑰與存儲在設備加密文件(/data/system_de/
最後,將令牌和哈希密鑰組合起來生成applicationId,從中派生出的CE密鑰與Gatekeeper模式中提供的密鑰相同。
Weaver的PoC隨著安全芯片在越來越多的設備中變得越來越流行,Weaver是Android系統中相對較新的成員。在Quarkslab,研究人員花了很多時間研究Titan M芯片,這是谷歌在Pixel 3中引入的。
總結Android磁盤加密絕對是一個突破性的功能,其安全性可以說是密不透風,設計者通過組合不同組件的功能,很好的保護了Android系統數據,攻擊者只有找到非常強大的漏洞才能發起攻擊。另外,受信任的芯片又把安全級別提高到了一個新的高度。