蘋果的OTA更新在大多數情況下,macOS更新是通過OTA更新過程完成的。
OTA是over-the-air的縮寫。在“系統設置”中,我們可以通過點擊“立即更新”按鈕直接更新系統。
OTA更新是一種增量更新,因此比完整的操作系統升級更快,容量更小。
它用於小版本更新,通常每兩個月更新一次。但是,如果蘋果公司認為內核中存在緊急漏洞,並且已經被積極利用,並且無法通過RSR(快速安全響應)修復,則可能在幾週內可用,OTA更新包從Apple CDN服務器下載。
從表中可以看到,OTA包是針對當前操作系統版本定制的。
例如,為了更新到12.6,12.5和12.4的軟件包是不同的。更新過程是應用補丁碼,所以不同的操作系統版本有不同的補丁碼。在大多數情況下,系統越老,包就越大。
下載並解壓縮OTA包後,我們可以看到包的內容如下:
引導目錄包含與引導過程相關的內容,增量更新的真正補丁代碼位於名為payloadv2的目錄中。有一個名為payload.bom的關鍵文件,它列出了OTA包中的所有項目及其校驗和值。文件payload.bom.signature用於驗證payload.bom文件的完整性。文件pre.bom和post.bom列出了更新前後系統上的所有項目及其校驗和值。 Info.plist文件提供了有關當前OTA包的一些基本信息,例如預版本、目標版本等。
在payloadv2文件夾中,有一些需要注意的重要文件。新系統中的新數據文件被壓縮為名為data_payload的文件。 ecc_data文件夾包含一些與文件權限相關的文件。 links.txt文件列出了新系統的所有硬鏈接。 removed.txt文件列出了需要從當前系統中刪除的所有項目。
更新階段一般的更新過程可以抽象為3個階段。
第一步是下載並解壓縮UpdateBrainService 捆綁包。
第二階段是下載並解壓縮OTA包。
第三個階段是使用OTA包生成UpdateBrainService。
那麼,系統從哪裡下載UpdateBrainService呢?
經過一些研究,我發現下載網址位於XML文件/System/Library/AssetsV2/com_apple_MobileAsset_MobileSoftwareUpdate_MacUpdateBrain/com_apple_MobileAsset_MobileSoftwareUpdate_MacUpdateBrain. XML:
從這個文件中,我們可以看到基本URL和構建完整URL的相對路徑。它還包含版本、發布日期、包大小、SHA1值和其他有用的信息。
第一階段
獲取下載URL後,進程nsurlessiond負責將UpdateBrainService下載到臨時目錄。同時,com.apple.StreamingUnzipService將其解壓縮到相同的臨時位置。接下來,mobileassetd進程將解壓的內容移動到可信位置,/System/Library/AssetsV2/com_apple_MobileAsset_MobileSoftwareUpdate_MacUpdateBrain/。最後,在啟動的進程生成UpdateBrainService之前,xpc服務包將被複製到它的暫存路徑。
第二階段第二階段與第一階段相似:
不同之處在於xml路徑/System/Library/AssetsV2/com_apple_MobileAsset_MacSoftwareUpdate/com_apple_MobileAsset_MacSoftwareUpdate.xml,
下載url和目標位置/System/Library/AssetsV2/com_apple_MobileAsset_MacSoftwareUpdate/。
第三階段第三個階段是UpdateBrainService本身。
特定的xpc服務有許多有趣的權限:
例如,“com.apple.rootless.install.heritable”授予其自身及其所有子進程修改SIP保護位置的權限。此外,“com.apple.apfs.reverse to snapshot”和“com.apple.private.apfs.create sealed snapshot(創建密封快照)”權限可能允許服務在重新啟動後更新受SSV保護的內容。
我們還應該注意的一點是,它是用標誌庫驗證進行簽名的。因此,我們不能通過將動態庫注入到這項服務中來直接享受這些權限。
逆轉UpdateBrainService
com.apple.MobileSoftwareUpdate.UpdateBrainService2
通過簡單的逆向工程,我們發現它提供了一個名為com.apple.MobileSoftwareUpdate.UpdaterainService2的mach服務,該服務具有一個稱為MSUBrainPrivateSXPCI接口的協議。
它通過在委託方法中返回YES直接接受來自任何客戶端的所有xpc連接:
但在研究過程中,我意識到服務中的協議方法沒有實現,所以我可能會在未來的版本中再次檢查。
com.apple.MobileSoftwareUpdate.UpdateBrainService
還有一個名為com.apple.MobileSoftwareUpdate.UpdateBrainService的服務。它是通過C語言的低級XPC API實現的:
在xpchandler(Handler主要用於異步消息的處理:當發出一個消息之後,首先進入一個消息隊列,發送消息的函數即刻返回,而另外一個部分在消息隊列中逐一將消息取出,然後對消息進行處理,也就是發送消息和接收消息不是同步的處理。)方法中,我們可以看到它通過一個全局數組來調度xpc請求:
如果xpc客戶機具有相應請求所需的權限,則服務將相應地調用處理例程函數。
全局調度表有7個元素,每個元素有3個成員:操作的名稱、所需的權限字符串和實際處理例程函數的地址。
繞過簽名驗證(CVE-2022-42791)修改包可以在應用補丁之前修改OTA包嗎?回顧之前討論過更新的第二階段,可以確認OTA包的最終路徑(/System/Library/AssetsV2/com_apple_MobileAsset_MacSoftwareUpdate/)被SIP保護。
但是,提取的內容首先被放置在一個臨時位置(/var/folders/zz/zyxvpxvq6csfxvn_n00000y800007k/T/
com.apple.nsurlsessiond/CFNetworkDownload_XXXXXX.tmp/[hash].asset),完全不受限制,它由nsurlsessiond所有,根用戶可以直接修改它。
因此,在mobileasseted進程移動到最終可信位置之前,有一個修改內容的時間窗口。因此,可信位置中的OTA包的內容是不可信的,需要進行驗證。
當我嘗試替換有效負載時。由於權限問題,mobileassetd進程無法調用文件API,因此拒絕移動到最終路徑:
但事實是,一旦通過檢測,它將調用API rename來移動包內容。所以我很早就替換了目標文件。
但一個成功的日誌是什麼樣的呢,如下圖所示:
幸運的是,有一個關鍵字字符串(“Moving file in …”)表明通過檢查的時間窗口。因此,一旦從日誌中監控到該關鍵字,我就可以替換目標文件。
接下來,我將進行第二次嘗試:
監控日誌,一旦檢測到關鍵字“Moving file”,就立即從OTA包中替換目標文件。
然後,被篡改的內容成功地傳輸到最終的可信位置!
但是,UpdateBrainService停止準備操作系統更新。
OTA包驗證此服務的職責是從可信位置驗證不可信的OTA包的內容。那麼,它如何驗證OTA包呢?
如上所述,payload.bom文件列出OTA包中的所有項目及其校驗和值:
下面是驗證包內容的函數:
它打開文件payload.bom並讀取其內容。接下來,該函數將payload.bom文件中指定的文件摘要值與最終路徑上的真實摘要值進行比較:
如果其中一個摘要值不等於期望值,則該函數返回false並且驗證失敗。
它如何驗證payload.Bom文件本身?另一個名為verify_package_signature的函數負責驗證:
首先,它打開payload.bom文件併計算其SHA1值。然後打開payload. dom .signature文件並讀取簽名文件內容。
接下來,它從系統證書文件(/System/Library/SoftwareUpdateCertificates/iPhoneSoftwareUpdate.pem)中獲取公鑰,該文件受SIP和SSV保護:
最後,它通過調用來自Security.framework的API seckeyverifysignsignature,用公鑰計算出的SHA1值和簽名文件內容驗證簽名:
TOCTOU漏洞這樣,在驗證中存在一個經典的TOCTOU (Time-Of-Check-Time-Of-Use)漏洞:
位於受信任位置的payload.bom文件不能直接修改,但我們可以在mobileassetd進程移動OTA包之前用符號鏈接替換它。因此,可以使用符號鏈接隨時修改payload.bom文件。
接下來,在函數verify_package_signature中,它根據符號鏈接從受控位置讀取BOM文件,因此我們使用原始payload.BOM來通過檢查。
然後在函數verify_package_contents中,它也遵循符號鏈接並使用受控BOM文件驗證OTA包中的所有其他項。所以現在,我們可以模擬payload.bom文件以替換OTA包中的所有其他項。
經過三次嘗試,終於實現了:
將原始payload.bom複製到受控位置/tmp/ppayload.bcom。
監控日誌,一旦檢測到關鍵字“Moving file”,就用指向/tmp/playload.bom的符號鏈接替換payload.bom。
符號鏈接(/tmp/payload.bom)已成功移動到最終受信任的位置!
在傳遞函數verify_package_signature後,偽造BOM文件(/tmp/payload.bom) 。
現在,OTA包中的所有項目都可以被篡改!
漏洞利用1:SIP繞過第一個漏洞是繞過SIP,這很容易做到。
函數ParallelPatchRemoveFiles讀取OTA包中的deleted .txt文件,並刪除txt文件中指定的所有項:
因此,我可以通過修改txt文件獲得一個原語來刪除任意受sip保護的路徑。
該漏洞適用於所有Mac平台,包括英特爾Mac和Apple Silicon Mac。
漏洞利用2:攻擊內核那麼,我可以劫持新的操作系統內核嗎?
使用SSV
繞過SIP後直接劫持OS內核的挑戰是SSV保護。
signed system volume (SSV)是macOS Big Sur中引入的新功能。在SIP被繞過的情況下,它仍然使用隔離的只讀系統卷來保護系統文件。
最基本的事實是,蘋果需要通過OTA更新來更新操作系統內核文件。因此,OTA更新過程必須具備突破SSV保護的能力。
但是這個過程是如何完成的呢?
macOS系統有一個隱藏的更新卷(/System/Volumes/Update/mnt1),它是當前操作系統的快照。然後將所有補丁應用於該快照。如果更新過程成功,它將更新密封值並引導新的操作系統。如果更新失敗,它將恢復到以前的快照。
在深入研究了UpdateBrainService之後,我總結了OTA更新過程中的關鍵工作流,如下所示:
首次嘗試首次嘗試是通過有效負載提取函數釋放一個精心製作的內核文件。
製作data_payload的步驟如下:
在OTA更新過程中,按照預期將精心製作的data_payload提取到快照中。
不過,重啟後它就不起作用了,目前還不確定是什麼原因。
第二次嘗試我的第二種方法是濫用應用修復的copy_patched_files函數。這與OTA更新過程更新內核的方式相同。
然而,困難在於我必須自己創建修復文件,它是BXDIFF 5格式的,並且沒有文檔記錄。所以,我必須先研究一下文件格式。
BXDIFF 5文件格式穀歌搜索這個文件格式後,我找到兩個GitHub存儲庫,它們都用於將修復文件應用於舊文件,然後生成新文件。但是,我需要基於兩個不同的文件生成一個修復文件。
但它們確實幫助我理解了文件格式,通過閱讀代碼,我知道BXDIFF 5文件由4部分組成:Header, Control, Diff和Extra。
Header部分的大小為88字節,前8個字節是硬編碼的魔術數字:
紅色的部分是未知的,似乎是無用的。綠色部分為修復前後的哈希值,用於驗證修復是否成功。藍色部分是以下部分的大小。
Control部分使用LZMA算法進行壓縮,解壓後的Control段數據為24字節,由3種控制命令組成:
第一個是混合長度,它指定從Diff部分混合多少字節。第二個是複制長度,第三個是查找長度。
Diff部分和Extra部分也是LZMA壓縮的。解壓縮後,數據是一個原始字節數組,以前由Control部分使用。
製作一個精心製作的修復程序文件我的目標是替換內核中系統命令uname的輸出字符串。所以我應該修改Diff部分。
首先,使用以下腳本計算Diff節中的新字節。
然後計
Recommended Comments