OS X IOBluetoothFamily.text中的內核 UAF 漏洞
當你從用戶空間創建一個新的 IOKit 用戶端時,將會調用:
kern_return_t IOServiceOpen( io_service_t service,ntask_port_t owningTask, uint32_t type, io_connect_t *connect );
參數 owningTask 埠通過 MIG 反序列化代碼轉化為一個任務結構指針,然後獲得對任務的引用,調用is_io_service_open_extended 時傳入 task 結構體,在這之後丟棄這個引用。
is_io_service_open_extended接著會調用該服務重寫的newUserClient 或者 initWithTask 的方法的實現。
如果這些服務想要保留指向owningTask 的指針,那麼就有必要實際持有一個引用。
實際上我們可以讓任意一個任務埠作為 owningTask,也就是說,如果用戶端沒有持有引用,我們可以非常輕鬆的通過任務埠進行另一項任務,關閉這個任務(釋放任務結構),然後通過用戶端來使用被釋放的任務結構。
IOBluetoothHCIUserClient(IOBluetoothHCIController 的 type 0n用戶端)可以在沒有引用的前提下,由一個普通用戶來實現,並在當前地址 + 0xe0 處存儲一個原始的任務結構指針。
這個指針將在稍後被用於IOBluetoothHCIUserClient::SimpleDispatchWL 中,來構建和操作 IOMemoryDescriptors。
此 POC 會 fork 一個子進程,並向父進程發送它的埠號,然後轉向。父進程將會創建一個新的 IOBluetoothHCIUserClient,將子進程的任務埠作為owningTaskn參數來傳遞,然後殺掉子進程(釋放它的任務結構)。接著父進程在用戶端調用一個外部方法,導致UAF。
IOMemoryDescriptor的代碼在處理任務結構方面做了一些奇怪的事情,並且內存映射釋放它,使得這個 bug成為一個簡單的可利用的內存崩潰問題,並且可以被用來做一些更有趣的邏輯處理 。
注意:必須打開藍牙,這個POC才有效。
build: clang -o bluetooth_uaf bluetooth_uaf.c -frameworknIOKit
你可以設置gzalloc_min=1024,gzalloc_max=2048 或者類似於UAF的實際錯誤,否則可能會得到一些奇怪的崩潰 。
已在 MacBookAir5,2 ,OS X 10.11.5(15F34)上測試。
註:附上 [Exploit] ( Apple OS X Kernel - IOBluetoothFamily.kext Use-After-Freen)推薦閱讀:
※花無涯帶你走進黑客世界5 黑客歷程
※繼續說我和隔壁老王 WiFi 的事 —— 續集
※Pwn2Own2017專題:VMWARE UAF漏洞分析