作者: Qixun Zhao(@S0rryMybad) of Qihoo 360 Vulcan Team
原文鏈接:https://blogs.projectmoon.pw/2019/10/30/iOS-13-1-3-Full-Chain-Eop/

該漏洞修復于 iOS 13.2, CVE 編號未明, 本來我打算用于 TianfuCup 的 iPhone rjb(當然還單純只有漏洞^^), 但是遺憾在比賽前十多天被修復了, 但是該漏洞的成因很簡單也很有趣. 關于 Safari 的漏洞我也會遲點寫個 post.

漏洞出在最近添加的一個 syscall: kqueue_workloop_ctl, 它之后會調用底層函數 kqueue_workloop_ctl_internal. 在漏洞路徑上沒有任何 MACF check, 也就是說它可以用于任何沙盒內的提權, 包括 Safari.

kqueue_workloop_ctl_internal 函數內一共有兩個問題, 第一個問題出在如下代碼:

我們可以看到, 假如 TRP_RELEASED 這個 flag 沒有設置, 就會調用 kqueue_release 兩次, 一共減去兩個引用計數, 如果設置了, 就代表這個 kq 已經被釋放過了, 就只調用一次減去一個引用計數, 這一個引用計數是對應 kevent_get_kq 這個函數加上去的.

咋一看沒有任何問題, 既可以避免了 race 的發生, 也可以避免多次釋放同一個kq, 導致 over release.但是問題的關鍵在于這個 flag 設置在了一個棧變量上,而不是堆變量上, 也就是說, 無論如何設個 flag 都不會為 true.

因此這個問題的起因雖然很簡單, 但是也很難發現, 因為代碼看上去沒有任何的問題, 如果不連著上面的|trp|變量的來源一起看的話.關于 poc 的觸發可以有兩種方式, 第一種是通過 race, 導致 over release, 第二種是把 kq 掛在一個別的對象身上, 先把引用計數加一, 然后通過這個漏洞多次釋放, 把對象引用計數減到 0 然后釋放, 再通過別的對象的指針引用產生 UaF. 這里我的 poc 比較簡單, 就是通過 race 觸發, 如果要寫 exploit, 則第二個觸發方法比較靠譜:

關于漏洞的補丁很簡單, 就是 flag 必須要設置到堆變量里, 不然產生不了任何效果:

至于第二個問題則存在于 kevent_get_kq 中, 留給讀者自己去發現.


Paper 本文由 Seebug Paper 發布,如需轉載請注明來源。本文地址:http://www.bjnorthway.com/1066/