天天看點

iOS冰與火之歌(番外篇) - 基于PEGASUS(Trident三叉戟)的OS X 10.11.6本地提權

蒸米@阿裡移動安全

這段時間最火的漏洞當屬阿聯酋的人權活動人士被apt攻擊所使用的ios pegasus(又稱trident三叉戟)0day漏洞了。為了修複該漏洞,蘋果專門釋出了一個ios 9.3.5版本。這個漏洞的厲害之處在于可以直接從沙盒内對核心進行攻擊(無需沙盒逃逸),并且同時影響ios(9.3.4)和os x (10.11.6)。是以,本篇文章将會從pegasus漏洞形成的原因開始分析,然後一步一步教大家寫出os x上利用pegasus提權的攻擊代碼。

《ios冰與火之歌》這一系列文章的目錄如下:

1. objective-c pwn and ios arm64 rop

2. 在非越獄的ios上進行app hook(番外篇)

3. app hook答疑以及ios 9砸殼(番外篇)

4. 利用xpc過app沙盒

5. uaf and kernel pwn

6. 基于pegasus(三叉戟)的os x 10.11.6本地提權 (番外篇)

pegasus(三叉戟)實際上是由三個漏洞組成,分别是:

<b>cve-2016-4657</b>:safari的webkit核心上的記憶體破壞漏洞。

<b>cve-2016-4655</b>:核心資訊洩露漏洞,可用于繞過kaslr。

<b>cve-2016-4656</b>:核心uaf漏洞,可用于控制核心并執行任意代碼。

關于cve-2016-4657目前還沒有公開的資料,但stefan esser和pangu分别爆出了另外兩個漏洞cve-2016-4655和cve-2016-4656的細節。利用已經曝光的這兩個漏洞,其實已經可以做到ios非完美越獄和os x本地提權了。下面我們就來講解一下這兩個漏洞形成的原因以及如何利用。

cve-2016-4655這個漏洞形成的原因是核心在序列化和反序列化osnumber的時候沒有驗證長度的正确性。是以,如果我們将number的長度設定的非常長,并用io_registry_entry_get_property()去擷取number資料的話,就會造成核心的資訊洩露。

iOS冰與火之歌(番外篇) - 基于PEGASUS(Trident三叉戟)的OS X 10.11.6本地提權

我們知道核心棧中會儲存函數的傳回位址,是以我們可以利用這個傳回位址去計算出核心的kslide,進而攻破kaslr的保護。

那麼如何編寫利用代碼呢?我們先建立一個序列化後的dictionary。對核心來說,這個dictionary應該是這樣的:

但是我們對osnumber的長度進行了修改,變成了0x200:

發送這個給核心後,核心在反序列化的時候就會出現錯誤。随後我們使用 io_registry_entry_get_property_bytes() 這個使用者态函數就可以擷取到核心傳回的資料了。

iOS冰與火之歌(番外篇) - 基于PEGASUS(Trident三叉戟)的OS X 10.11.6本地提權

因為我們修改了os number的長度,是以傳回的資料不光有我們發送給核心的number,還有棧上資料,比如函數ret時候的傳回位址-0xffffff80003934bf。

iOS冰與火之歌(番外篇) - 基于PEGASUS(Trident三叉戟)的OS X 10.11.6本地提權

通過這個位址我們就可以計算出來kslide了。

cve-2016-4656這個漏洞其實有兩種觸發uaf的方法,我們這裡先講比較簡單的那一種(兩種方法在stefan esser的文章中都有介紹)。簡單uaf漏洞形成的原因是osunserializebinary支援用osstring和ossymbol來作為key,并且支援用osobject去引用之前的key。但是osstring和ossymbol不一樣的地方在于,osstring key轉換為ossymbol的過程中osstring已經被free掉了,但這個osstring卻被加入了對象清單裡。

iOS冰與火之歌(番外篇) - 基于PEGASUS(Trident三叉戟)的OS X 10.11.6本地提權

是以當我們osobject類型去引用一個已經被釋放了的osstring的時候,就會産生uaf崩潰:

iOS冰與火之歌(番外篇) - 基于PEGASUS(Trident三叉戟)的OS X 10.11.6本地提權

通過彙編崩潰的位置我們可以找到源碼對應的位置是在341行建立osobject對象的時候:

iOS冰與火之歌(番外篇) - 基于PEGASUS(Trident三叉戟)的OS X 10.11.6本地提權

是以,如果我們能夠在osstring被free的時候,立刻申請一段和osstring一樣大小的記憶體并且構造好對應的vtable資料,當程式執行到osobject建立的時候,核心就能成功的被我們控制。

那麼如何編寫利用代碼呢?我們還是先建立一個序列化後的dictionary。對核心來說,這個dictionary應該是這樣的:

核心随後會解析這個dictionary,正如我們之前分析的,osstring-”a”在建立完後就被free掉了,這時候,我們立刻建立ossymbol-”b”以及和osstring-”a”大小相同的osdata,就可以在osstring-”a” free後重新控制這塊記憶體,随後當核心使用osobject引用osstring-”a”,并調用retain()函數的時候,其實就是在調用我們已經控制的vtable了。

首先我們先申請一塊記憶體來放vtable和rop chain,在os x上有一種取巧的方法,如果我們是32位的程式的話,可以使用null page。是以,我們先用vm_allocate()申請到null page,然後将vtable和rop chain都儲存在null page裡:

iOS冰與火之歌(番外篇) - 基于PEGASUS(Trident三叉戟)的OS X 10.11.6本地提權

随後在os x上用rop提權的代碼我們可以直接使用tpwn的:首先獲得目前程序的ucred,然後将cr_svuid設定為0,最後用thread_exception_return退出程序。

iOS冰與火之歌(番外篇) - 基于PEGASUS(Trident三叉戟)的OS X 10.11.6本地提權

編寫完代碼後,我們來嘗試執行一下我們的exp。

首先說一下測試環境:mac os x ei capitan 10.11.6 (15g31),在沒有安裝2016-01的security update的情況下(這時候核心相當于ios 9.3.4,如果安裝完2016-01 update就相當于ios 9.3.5)。

iOS冰與火之歌(番外篇) - 基于PEGASUS(Trident三叉戟)的OS X 10.11.6本地提權

接下來我們編譯一下我們的exp:

clang -framework iokit -framework foundation -framework corefoundation -m32 -wl,-pagezero_size,0 -o3 exp.m lsym.m -o exp

然後運作:

iOS冰與火之歌(番外篇) - 基于PEGASUS(Trident三叉戟)的OS X 10.11.6本地提權

可以看到我們已經成功的擷取了root權限。

這篇文章介紹了如何利用pegasus(trident三叉戟)做到核心資訊洩露以及核心代碼執行,然後利用rop擷取root權限。另外,因為pegasus(trident三叉戟)同時存在于ios和os x,有興趣的同學可以在我們釋出的攻擊代碼的基礎上,嘗試一下ios攻擊代碼的編寫。

1. http://blog.pangu.io/cve-2016-4655/

2. https://sektioneins.de/en/blog/16-09-02-pegasus-ios-kernel-vulnerability-explained.html

3. https://bazad.github.io/2016/05/mac-os-x-use-after-free/

4. https://github.com/kpwn/tpwn

阿裡聚安全由阿裡巴巴移動安全部出品,面向企業和開發者提供企業安全解決方案,全面覆寫移動安全、資料風控、内容安全、實人認證等次元,并在業界率先提出“以業務為中心的安全”,賦能生态,與行業共享阿裡巴巴集團多年沉澱的專業安全能力。

繼續閱讀