再談CVE-2017-7047 Triple_Fetch和iOS 10.3.2沙盒逃逸
0x00 序
Ian Beer@google發布了CVE-2017-7047Triple_Fetch的exp和writeup[1],chenliang@keenlab也發表了關於Triple_Fetch的分析[2],但由於這個漏洞和exp有非常多的亮點,所以還剩很多可以深入挖掘的細節。因此,我們簡單分析一下漏洞形成的原因,並具體介紹一下漏洞利用的細節,以及如何利用這個漏洞做到iOS 10.3.2上的沙盒逃逸。
0x01 CVE-2017-7047 Triple_Fetch漏洞形成的原因
因為chenliang對漏洞成因的分析非常詳細,這裡我就簡單描述一下,因為使用XPC服務傳輸大塊內存的話很影響效率,蘋果為了減少傳輸時間,對大於0x4000的OS_xpc_data數據會通過mach_vm_map的方式映射這塊內存,然後將這塊數據的send right以port的方式發送到另一方。但這段內存的共享是基於共享物理頁的方式,也就是說發送方和接收方會共享同一塊內存,因此我們將數據發送以後再在發送端對數據進行修改,接收方的數據也會發生變化。
因此通過race condition,可以讓接收端得到不同的數據(接收端認為是相同的數據),如果接收端沒有考慮到這一點的話就可能會出現漏洞。比如我們剛開始讓接收端獲取的字元串是@」ABCD」(包括@和」),那麼接收端會為這個字元串分配7個位元組的空間。隨後在進行字元串拷貝的時候,我們將字元串變為@"ABCDOVERFLOW_OVERFLOW_OVERFLOW",接收端會一直拷貝到遇到」符號為止,這樣就造成了溢出。
Triple_Fetch攻擊所選擇的函數是CoreFoundation里的___NSMS1()函數,這個函數會對我們構造的惡意字元串進行多次讀取操作,如果在讀取的間隙快速對字元串進行三次修改,就會讓函數讀取到不同的字元串,讓函數產生判斷失誤,從而造成溢出並讓我們控制pc,這也是為什麼把這個漏洞稱為Triple_Fetch的原因。下圖就是攻擊所使用的三組不同的字元串:
攻擊所選擇的NSXPC服務是「com.apple.CoreAuthentication.daemon」。對應的二進位文件是/System/Library/Frameworks/LocalAuthentication.framework/Support/coreauthd。原因是這個進程是root許可權並且可以調用processor_set_tasks() API從而獲取系統其他進程的send right[3]。下圖是控制了pc後的crash report:
0x02 Triple_FetchJOP &ROP&任意代碼執行
利用漏洞Triple_Fetch雖然可以控制pc,但是還不能控制棧,所以需要先做stack_pivot,好消息是x0寄存器指向的xpc_uuid對象是我們可以控制的:
因此我們可以利用JOP跳轉到_longjmp函數作為來進行stack pivot,從而控制stack:
最終發送的用來做JOP的格式偽造的xpc_uuid對象如下:
控制了stack就可以很容易的寫rop了。但是beer目標不僅僅是執行rop,它還希望獲取目標進程的task port並且執行任意二進位文件,因此除了exp,攻擊端還用mach msg發送了0x1000個帶有send right的port到目標進程中:
這些port的mach msg在內存中的位置和內容如下(msgh_id都為0x12344321):
隨後,exp採用rop的方法對這些port進行遍歷並且發送回發送端:
隨後,攻擊端會接收mach msg,如果獲取到的msgh_id為0x12344321的消息,說明我們成果得到了目標進程的task port:
得到了task_port後,sploit()函數就結束了,開始進入do_post_exploit()。do_post_exploit()也做了非常多的事情,首先是利用coreauthd的task port以及processor_set_tasks()獲取所有進程的task port。這是怎麼做到的呢?
利用coreauthd的task port我們可以利用mach_vm_* API任意的修改coreauthd的內存以及寄存器,所以我們需要先開闢一段內存作為stack,然後將sp指向這段內存,再將pc指向我們想要執行的函數地址就可以讓目標進程執行任意的函數了,具體實現在call_remote()中:
隨後我們控制coreauthd依次執行task_get_special_port(), processor_set_default(), host_processor_set_priv(),processor_set_tasks()等函數,來獲得所有進程的task port並返回給攻擊端(具體實現在get_task_ports())中。接著,攻擊端會遍歷這個列表並篩選出amfid,launchd,installd,springboard這四個進程的task port。然後利用之前patch amfid的技巧,對amfid打補丁。最後再啟動debugserver。
其實這個exp不但可以執行debugserver,還可以用來在沙盒外執行任意的二進位文件。只要把pocs文件夾下的hello_world二進位文件替換成你自己的想要執行的二進位文件,編譯安裝後,點擊ui中的exec bundle binary即可:
具體怎麼做到的呢?秘密在spawn_bundle_binary()函數中,先在目標進程中調用chmod將bin改為0777,然後通過一系列的posix_spawn API(類似fork())在目標進程中執行該bin文件。
沙盒外的代碼執行提供了更多可以攻擊內核的介面。並且可以讀取甚至修改其他應用或者系統上的文件。比如,漏洞可以讀取一些個人隱私數據(比如,簡訊,聊天記錄和照片等)並發送到黑客的伺服器上:
所以建議大家早日更新iOS系統到最新版本。
0x03 總結
本文介紹了beer發現的通用NSXPC漏洞。另外,還分析了iOS用戶態上,用JOP做stack pivot以及利用ROP做到任意代碼執行的攻擊技術。當然,這些漏洞只是做到了沙盒外的代碼執行,想要控制內核還需要一個或兩個XNU或者IOKit的漏洞才行,並且蘋果已經修復了yalu102越獄用的kpp繞過方法,因此,即使有了Triple_Fetch漏洞,離完成全部越獄還有很大一段距離。
0x04 參考文獻
1、https://bugs.chromium.org/p/project-zero/issues/detail?id=1247
2、http://keenlab.tencent.com/zh/2017/08/02/CVE-2017-7047-Triple-Fetch-bug-and-vulnerability-analysis/
3、http://newosxbook.com/articles/PST2.html
英文版鏈接:https://jaq.alibaba.com/community/art/show?articleid=1020
------------------
* 作者:蒸米,更多安全知識分享和熱點信息,請關注阿里聚安全的安全專欄和官方博客
推薦閱讀:
※目錄遍歷漏洞
※Apache OpenOffice更新修復四個中危漏洞
※兒童電話手錶的安全漏洞會造成哪些問題?如何避免
※讓我們一起來消滅CSRF跨站請求偽造(上)
※一驚一乍的「Wi-Fi 漏洞」新聞嚇到你了?淡定些來聽聽安全專家怎麼說