不可忽視的安全威脅:深入揭露 macOS Race Condition

macOS 核心中存在一個嚴重的Race condition漏洞 (CVE-2025-24118)。此錯誤源自於 zalloc_ro_mut 函數中的非原子(Non-atomic) memcpy 操作,它導致程序的認證指標(Credential pointer)被破壞。該漏洞利用了 macOS 的Safe Memory Reclamation (SMR) 和唯讀頁面映射(Page mapping),從而實現了潛在的權限提升。概念驗證攻擊涉及快速改變程序群組 ID(Process group ID) 來觸發Race condition。建議的修復使用原子替代函數替換非原子函數。

 揭露隱藏的macOS漏洞:你的系統是否安全? | 資訊安全新聞

技術細節與機制

本文詳細介紹了 macOS 核心中的Race condition漏洞,特別是 CVE-2025-24118,該漏洞允許破壞執行緒的 kauth_cred_t 認證指標。此漏洞源自於對安全記憶體回收 (SMR) 保護指標的非原子(Non-atomic)更新,從而導致潛在的權限提升。以下是該漏洞的關鍵概念和機制的細分:
  • 安全記憶體回收 (SMR):SMR 是一種無鎖(lock-free)記憶體管理技術,允許協同(Concurrent)讀取和寫入資料結構。在 XNU(macOS 核心)中,SMR 使用Epoch-based system,其中全域計數器會隨著時間的推移而遞增,並且執行緒會追蹤它們觀察到的Epoch。當沒有執行緒使用記憶體時,它可以被釋放。
  • 唯讀頁面:XNU 透過將敏感資料儲存在唯讀頁面中來保護它們。這些頁面只能透過特定的 API 進行修改。 zalloc_ro_mut API 用於修改唯讀區域中的資料。但是在 X86_64 上,該 API 使用了由 rep movsb 實現的 memcpy,它不是原子的並且逐位元組複製。
  • 每個執行緒的認證:在 XNU 中,每個執行緒可以擁有自己的一組認證(struct ucred),用於儲存與安全性相關的信息,例如使用者 ID。這些認證資料通常使用Hash Table共享以節省記憶體使用,但可以獨立更新。 proc_ro 結構是唯讀的,它保存指向程序認證的 SMR 指標。
  • Race condition:漏洞存在於函數 kauth_cred_proc_update 中,該函數更新唯讀 proc_ro 結構中的 p_ucred 指標。此指標受 SMR 保護,因此需要原子更新(atomic update)。然而,kauth_cred_proc_update 使用 zalloc_ro_mut 來更新 p_ucred 指標,如上所述,它在 X86_64 上不是原子操作。 此非原子寫入可與每次系統呼叫期間發生的 p_ucred 讀取競爭。
  • 漏洞利用:
    1. 寫入執行緒使用 setgid 重複更改程序的群組 ID。這會強制核心系統呼叫 kauth_cred_proc_update 以非原子方式更新 p_ucred 指標。
    2. 讀取器執行緒迴圈執行系統呼叫(例如 getgid())。在系統呼叫期間,核心透過讀取 p_ucred 指標來檢查目前執行緒的認證是否與程序的認證相符。
    3. 如果在寫入過程中發生讀取,則讀取器可以取得部分寫入的 p_ucred 值。這可能會導致Crash,或者更危險的是,指標可能指向另一個有效的認證物件,從而可能提升權限。
  • 修復:建議的修復方法是將 zalloc_ro_mut 替換為 zalloc_ro_mut_atomic,以確保對 p_ucred 的更新是原子操作。
  • 其他注意事項
    1. 此漏洞很難觸發,因為切換的兩個憑證指標位於相同記憶體區域,因此在其位址中共用許多相同的位元組。
    2. 作者僅在 Intel 系統上觀察到此錯誤。他們認為這是因為 ARM64 上使用的 memcpy 實作一次複製更大的記憶體區塊,從而產生了某種實際層級的原子性,儘管不是嚴格的原子性。
    3. 此錯誤已在 macOS 15.3 中修正。

結論

這篇文章描述了 macOS 核心中的一個關鍵Race Condition漏洞(CVE-2025-24118),源於對受 Safe Memory Reclamation(SMR)保護的指標 `p_ucred` 在唯讀 `proc_ro` 結構中的非原子寫入。`kauth_cred_proc_update` 函數錯誤地使用 `zalloc_ro_mut`(該方法通過在 X86_64 上使用 `rep movsb` 進行非原子 `memcpy`)來更新 `p_ucred`,而不是使用原子操作,這違反了 SMR 的要求。這個非原子寫入可能會與協同(Concurrent)讀取發生競爭,最終導致認證指標損壞。

攻擊利用涉及一個寫入執行緒使用 `setgid` 反覆觸發對 `p_ucred` 的更新,以及一個讀取執行緒執行會Dereference該指標的系統呼叫。成功利用此漏洞可能導致核心恐慌(Kernel Panic),或者更嚴重的情況是,認證物件被更改為有效但不同的物件,從而導致特權提升。修復方法是將 `zalloc_ro_mut` 替換為 `zalloc_ro_mut_atomic`,以確保原子更新。這個漏洞在 macOS 15.3 中已經解決。這個漏洞凸顯了在協同操作中原子性的的重要性,以及看似微不足道的實現細節可能會引入重大安全問題。