CVE-2019-8561:難纏的 macOS PackageKit 框架漏洞

本文詳細說明我們對 CVE-2019-8561 漏洞的研究,這是一個存在於 macOS 軟體安裝套件 (PKG 檔案) 安裝框架「PackageKit」當中的漏洞。

本文詳細說明趨勢科技對 CVE-2019-8561 漏洞的研究,這是一個存在於 macOS 軟體安裝套件 (PKG 檔案) 安裝框架「PackageKit」當中的漏洞。我們將討論 Apple 如何修補這個漏洞,漏洞修補之後我們如何繼續攻擊這個漏洞,以及後續 Apple 又如何再次修補。

此外,我們也通報了超過 15 個規避 Apple SIP 機制的漏洞給 Apple,其中有些漏洞我們曾在 Power of Community 2022 Security Conference (POC2022) 研討會上討論過。本文是我們一系列討論 Apple SIP 相關漏洞的部落格之一。

CVE-2019-8561 漏洞簡史


2019 年 3 月 25 日,蘋果修正了 CVE-2019-8561 漏洞,這是一個可能讓駭客提升至系統管理員 (root) 權限、規避簽章,最終規避 Apple 系統完整性保護 (System Integrity Protection,簡稱 SIP) 機制的一個漏洞。

就在該漏洞揭露的三個月後,研究人員  Jaron Bradley 在第二屆 Objective by the Sea 資安研討會上說明了這個漏洞。這場名為「Bad Things in Small Packages」(壞事不必大) 的演講,激起了我們對 Apple 如何修正 CVE-2019-8561 漏洞的好奇。經過深入研究 PackageKit 框架之後,我們發現 Apple 當時最新版的桌面作業系統 macOS (Monterey) 依然存在著 CVE-2019-8561 漏洞的問題。就像在之前的 macOS 10.14 (Mojave) 當中一樣,此漏洞可用來提升權限並避開 SIP 機制的限制。

2022 年 10 月 24 日,Apple 又再次於 macOS 13 (Ventura) 當中解決了這個問題,漏洞編號為 CVE-2022-32895 。

Apple 的 SIP 機制  

SIP  是從 OS X EI Capitan 開始導入的一項安全機制,目的是要保護 Mac 作業系統,防止惡意軟體修改受保護的檔案和資料夾。它會限制 root 使用者帳號 (因此又稱為 rootless機制) 並限制 root 使用者可以對作業系統受保護部分做哪些動作。

在 SIP 導入之前,root 使用者的權限是沒有限制的,這意味著他們可以存取電腦上的任何系統資料夾或應用程式。但有了這項安全機制之後,唯有經過 Apple 簽署或擁有特殊授權 (entitlement) 的處理程序才可以修改受保護的系統檔案,這些處理程序包括 Apple 軟體更新與安裝程式。

system_installd


Mac 作業系統需一些特殊授權才能更新系統檔案,例如「com.apple.rootless.install」和「com.apple.rootless.install.heritable」這兩個授權,這些權限可針對特定用途來提供修改系統檔案的許可。

這些特殊授權只有 Apple 能夠使用,而且僅有少數系統指令在簽署時擁有這些特殊授權。「system_installd 」就是一個擁有這類授權的系統背景服務之一,它負責安裝 Apple 簽署的套件。該服務的核心邏輯實作在 PackageKit 框架當中,由於它擁有 com.apple.rootless.install.heritable 這個特殊授權,因此它產生的子處理程序就能在一個不受 SIP 限制的環境中執行。

CVE-2019-8561 的技術分析

CVE-2019-8561 簡介

CVE-2019-8561 利用的是 Apple 簽署的 PKG 檔案安裝過程當中暴露的經典「檢查時間與使用時間差」(time-of-check-to-time-of-use,簡稱 TOCTTOU)的問題。

圖 1 示範其攻擊過程:


圖 1:CVE-2019-8561 攻擊過程。

1.        安裝一個含有安裝前 (pre-install) 或安裝後 (post-install) 腳本的 Apple 簽署 PKG 檔案。

2.        system_installd  背景服務會處理安裝請求並檢查套件的簽章,若該服務判斷套件不是由 Apple 所簽署,就會放棄安裝程序。

3.        在通過該服務的驗證之後,駭客就將 PKG 檔案換成惡意版本。

4.        此時該服務會從冒牌、未經簽署的 PKG 檔案中擷取出惡意的安裝前或安裝後腳本來執行。

5.        該服務啟動的腳本就會在一個沒有 SIP 限制的環境中以 root 權限執行。

值得注意的是這個漏洞相當容易理解及攻擊,所以我們很好奇 Apple 是如何將它解決。

CVE-2019-8561 分析


當我們試圖攻擊當時最新版作業系統 macOS Monterey 的這個舊漏洞時,我們收到一個來自「xar_open_digest_verify」函式的錯誤訊息。

圖 2 顯示摘要值 (digest) 驗證函式的呼叫堆疊內容:


圖 2:摘要值 (digest) 驗證函式呼叫堆疊內容。

該訊息指出內容 (TOC) 摘要值不符合預期。

當我們對 PackageKit 框架中的函式呼叫堆疊進行逆向工程分析時,我們發現這個摘要值是從安裝用戶端所傳入。此外,它還會將要回傳的 XAR 壓縮檔指標儲存到一個變數當中。所以,當它下次需要存取 PKG 檔案時,就會直接從該變數傳回先前儲存的 XAR 指標,而非再次開啟 XAR 壓縮檔。


圖 3:PKXARArchive _xar 函式實作程式碼。

到這裡為止,Apple 的修補似乎發揮了作用,因為它在擷取內容時會先檢查摘要值。然而問題並非僅止於此。 

分兩次或三次讀取


由於一個 PKG 檔案可能非常大,通常不建議將其內容一次全部讀進記憶體內。所以,一般都是在需要時才讀取和解開內部的元件。

當我們解譯了 -[PKExtractInstallOperation _extractAllSpecifiersOnceAndReturnFailingSpecifier:andError:] 函式之後,我們發現它會呼叫三個不同的方法 (method) 來分別擷取成分清單 (BOM) 檔案、惡意內容,以及腳本。


圖 4:_extractAllSpecifiersXXX 方法。

第一個方法:-[PKExtractInstallOperation _extractBomForPackageSpecifier:error:] 會先檢查摘要值之後再擷取 BOM 檔案,如圖 2 所示。

第二個方法:-[PKExtractInstallOperation _extractScriptsForPackageSpecifier:error:] 的內部會呼叫 -[PKLeopardPackage scriptsExtractorWithDestination:error:] 函式。


圖 5:scriptsExtractorXXX 方法實作程式碼。

此外我們也研究了 -[PKPayloadCopier initWithArchivePath:offset:destination:] 函式。


圖 6:initWithArchivePathXXX 方法實作程式碼。

從圖 6 我們看到該函式會直接開啟 PKG 檔案 (第 20 行),從某個位移位置讀取要傳回的檔案描述元 (file descriptor),將檔案描述元放入 BOMCopier,並將輸入鍵 (Key) 設為「inputFD」。

接著我們繼續分析 -[PKPayloadCopier run] 函式。


圖 7:-[PKPayloadCopier run] 方法實作程式碼。

此函式呼叫 API 函式「BOMCopierCopyWithOptions」從未受信任的「inputFD」擷取資料。

使用 API 函式「xar_open_digest_verify」來開啟一個未受信任的 PKG 檔案是安全的,但「open」函式則不然。這是典型「分兩次讀取」漏洞:「open」函式會直接開啟未受信任 PKG 檔案而不再檢查它的摘要值,所以駭客可將 PKG 檔案置換成一個惡意版本,所以舊漏洞的問題依然存在。  

第三個方法:-[PKExtractInstallOperation _extractPayloadForPackageSpecifier:error:] 的內部會呼叫 -[PKLeopardPackage payloadExtractorWithDestination:externalRoot:error:] 函式。


圖 8:payloadExtractorXXX 方法實作程式碼。

在第 28 行,如果在 PKG 檔案當中,惡意內容的子路徑位移位值不是零,那麼 -[PKLeopardPackage payloadExtractorWithDestination:externalRoot:error:] 函式就會呼叫 -[PKPayloadCopier initWithArchivePath:offset:destination:] 函式。與前面第二個方法類似,這裡是典型的「分三次讀取」漏洞。

若位移值等於零,它就會從某個外部根路徑 (root path) 擷取惡意內容,而這似乎是不受限制,所以能被駭客操控。也就是說,駭客可以將惡意內容放在外部某個根路徑中。不過,截至本文撰稿為止,我們還無法找到一個 Apple 簽署的 PKG 檔案使用了一個外部根路徑。

漏洞攻擊


相較於舊的漏洞攻擊手法,這次的競爭情況 (race condition) 的持續時間較短。在擷取惡意內容之後,駭客必須將 PKG 檔案恢復至原本 Apple 簽署的版本,才能讓後續的驗證順利過關。而且還有一個挑戰必須克服:在新產生的 PKG 檔案當中,腳本或惡意內容的子路徑位移值必須與原始的版本相同才行。

為了攻擊這個舊漏洞,我們首先準備了一個特製的 PKG 檔案,裡面包含我們的惡意內容。接著將原始 Apple 簽署的 PKG 檔案展開,清除裡面原本的腳本,將我們的惡意內容放入安裝後腳本當中。

pkgutil –expand /Volumes/Pro\ Video\ Formats/ProVideoFormats.pkg /tmp/ProVideoFormats
rm -rf /tmp/ProVideoFormats/MXFPlugIns.pkg/Scripts/*
echo ‘#!/bin/bash’ > /tmp/ProVideoFormats/MXFPlugIns.pkg/Scripts/postinstall
echo ‘touch /Library/Apple/sip_bypass’ >> /tmp/ProVideoFormats/MXFPlugIns.pkg/Scripts/postinstall
chmod +x /tmp/ProVideoFormats/MXFPlugIns.pkg/Scripts/postinstall

接下來,為了克服腳本子路徑位移植的挑戰,我們撰寫了一個 Python 腳本,在一個無盡迴圈當中試圖建立這個新的 PKG 檔案,直到位移值符合要求為止。

while True:
os.system(‘pkgutil –flatten /tmp/ProVideoFormats /tmp/ProVideoFormats.fake.pkg’)
f=open(‘/tmp/ProVideoFormats.fake.pkg’, ‘rb’) 
f.seek(scriptsOffsetInPkg) # the offset value from the original PKG
if f.read(4)==’\x1f\x8b\x08\x00′: break
f.close()

做好這個特製 PKG 檔案之後,接下來就可以利用以下步驟攻擊漏洞:

1.        安裝一個 Apple 簽署的 PKG 檔案,裡面包含安裝後腳本。

2.        system_installd 背景服務會處理安裝請求。 

3.        在 -[PKLeopardPackage scriptsExtractorWithDestination:error:] 函式中,PKG 檔案會被置換成特製版本 (在第 8 行至第 16 行之間)。

4.        等到背景服務呼叫 API 函式「BOMCopierCopyWithOptions」來擷取我們特製 PKG 檔案中的惡意腳本之後,將 PKG 檔案恢復成原始版本。

5.        接著,system_installd 會建立一個不受 SIP 限制並具備 root 權限的環境來執行擷取出來的惡意腳本。

Apple 在 macOS Ventura 上的最新修補方式

Apple 後來又在 macOS Ventura 上解決了這個漏洞,作法如下:

首先,新的修補程式碼會透過可信賴的 XAR 指標讀取 PKG 檔案子路徑預期的總和檢查碼 (checksum) 屬性,該指標是由安全的 API 函式「xar_open_digest_verify」所回傳。


圖 9:新的修補程式碼會讀取預期的總和檢查碼 (checksum)。

接著,程式不再直接從「inputFD」讀取資料,而是使用一個 ObjC 類別的物件「IASInputStream」來讀取「inputStream」。在擷取過程中,也會同步更新「inputStream」的摘要值。


圖 10:從「inputStream」擷取資料。

擷取完成後,它會檢查「inputStream」實際的總和檢查碼是否與預期的相符。如果是,就繼續執行安裝。否則,就放棄安裝流程。


圖 11:檢查實際的總和檢查碼。

我們認為,最好的解決方法也許可以先將 PKG 檔案複製到一個安全位置再開始執行安裝流程。Apple 簽署的套件應該要被複製到一個受 SIP 保護的位置,其餘的套件則應該複製到一個 root 所擁有的位置。

不過,Apple 最新的修補已經成功地解決了這個漏洞。

資安建議

Apple 已釋出這個漏洞的修補更新,也成功地在今年的 macOS Ventura 當中解決了這問題。使用者若未更新自己的作業系統,有可能會遭遇駭客將自己提升到系統管理權限、避開簽章、避開 SIP 機制的情況。因此,使用者務必安裝所有更新來確保系統的安全。

此外,一般使用者也可採用一套資安產品,如 Trend Micro Antivirus for MacTrend Micro Protection Suites 來協助偵測及攔截專門利用這類漏洞的攻擊。

原文出處:CVE-2019-8561:A Hard-to-Banish PackageKit Framework Vulnerability in macOS 作者:Mickey Jin