请选择 进入手机版 | 继续访问电脑版
查看: 8047|回复: 2438

[Linux/Mac] MacOS X / iOS Suid Binary Logic Error kernel code execution Exploit

[复制链接]
  • TA的每日心情

    前天 11:29
  • 签到天数: 903 天

    [LV.10]以坛为家III

    发表于 2016-3-28 11:04:52 | 显示全部楼层 |阅读模式
    CVE-2016-1757

    [AppleScript] 纯文本查看 复制代码
    Source: [url]https://bugs.chromium.org/p/project-zero/issues/detail?id=676[/url]
      
    tl;dr
    The code responsible for loading a suid-binary following a call to the execve syscall invalidates
    the task port after first swapping the new vm_map into the old task object leaving a short race window
    where we can manipulate the memory of the euid(0) process before the old task port is destroyed.
      
    ******************
      
    __mac_execve calls exec_activate_image which calls exec_mach_imgact via the image activator table execsw.
      
    If we were called from a regular execve (not after a vfork or via posix_spawn) then this calls load_machfile
    with a NULL map argument indicating to load_machfile that it should create a new vm_map for this process:
      
      if (new_map == VM_MAP_NULL) {
        create_map = TRUE;
        old_task = current_task();
      }
      
    it then creates a new pmap and wraps that in a vm_map, but doesn't yet assign it to the task:
      
        pmap = pmap_create(get_task_ledger(ledger_task),
               (vm_map_size_t) 0,
               ((imgp->ip_flags & IMGPF_IS_64BIT) != 0));
        pal_switch_pmap(thread, pmap, imgp->ip_flags & IMGPF_IS_64BIT);
        map = vm_map_create(pmap,
            0,
            vm_compute_max_offset(((imgp->ip_flags & IMGPF_IS_64BIT) == IMGPF_IS_64BIT)),
            TRUE)
      
    the code then goes ahead and does the actual load of the binary into that vm_map:
      
      lret = parse_machfile(vp, map, thread, header, file_offset, macho_size,
                            0, (int64_t)aslr_offset, (int64_t)dyld_aslr_offset, result);
      
    if the load was successful then that new map will we swapped with the task's current map so that the task now has the
    vm for the new binary:
      
        old_map = swap_task_map(old_task, thread, map, !spawn);
      
        vm_map_t
        swap_task_map(task_t task, thread_t thread, vm_map_t map, boolean_t doswitch)
        {
          vm_map_t old_map;
      
          if (task != thread->task)
            panic("swap_task_map");
      
          task_lock(task);
          mp_disable_preemption();
          old_map = task->map;
          thread->map = task->map = map;
      
    we then return from load_machfile back to exec_mach_imgact:
      
      lret = load_machfile(imgp, mach_header, thread, map, &load_result);
      
      if (lret != LOAD_SUCCESS) {
        error = load_return_to_errno(lret);
        goto badtoolate;
      }
        
      ...
      
      error = exec_handle_sugid(imgp);
      
    after dealing with stuff like CLOEXEC fds we call exec_handle_sugid.
    If this is indeed an exec of a suid binary then we reach here before actually setting
    the euid:
      
           * Have mach reset the task and thread ports.
           * We don't want anyone who had the ports before
           * a setuid exec to be able to access/control the
           * task/thread after.
          ipc_task_reset(p->task);
          ipc_thread_reset((imgp->ip_new_thread != NULL) ?
               imgp->ip_new_thread : current_thread());
      
    As this comment points out, it probably is quite a good idea to reset the thread, task and exception ports, and
    that's exactly what they do:
      
      ...
      ipc_port_dealloc_kernel(old_kport);
      etc for the ports
      ...
      
      
    The problem is that between the call to swap_task_map and ipc_port_dealloc_kernel the old task port is still valid, even though the task isn't running.
    This means that we can use the mach_vm_* API's to manipulate the task's new vm_map in the interval between those two calls. This window is long enough
    for us to easily find the load address of the suid-root binary, change its page protections and overwrite its code with shellcode.
      
    This PoC demonstrates this issue by targetting the /usr/sbin/traceroute6 binary which is suid-root. Everything is tested on OS X El Capitan 10.11.2.
      
    In our parent process we register a port with launchd and fork a child. This child sends us back its task port, and once we ack that we've got
    its task port it execve's the suid-root binary.
      
    In the parent process we use mach_vm_region to work out when the task's map gets switched, which also convieniently tells us the target binary's load
    address. We then mach_vm_protect the page containing the binary entrypoint to be rwx and use mach_vm_write to overwrite it with some shellcode which
    execve's /bin/zsh (because bash drops privs) try running id in the shell and note your euid.
      
    Everything is quite hardcoded for the exact version of traceroute6 on 10.11.2 but it would be easy to make this into a very universal priv-esc :)
      
    Note that the race window is still quite tight so you may have to try a few times.
    回复

    使用道具 举报

  • TA的每日心情

    2015-10-24 10:52
  • 签到天数: 7 天

    [LV.3]偶尔看看II

    发表于 2016-3-28 14:38:11 | 显示全部楼层
    谢谢楼主的分享
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    慵懒
    2019-4-14 17:44
  • 签到天数: 5 天

    [LV.2]偶尔看看I

    发表于 2016-3-28 15:44:40 | 显示全部楼层
    支持中国红客联盟(ihonker.org)
    回复 支持 反对

    使用道具 举报

  • TA的每日心情

    2019-2-12 22:05
  • 签到天数: 2 天

    [LV.1]初来乍到

    发表于 2016-3-28 17:37:32 | 显示全部楼层
    我是来水经验的……
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    发表于 2016-3-28 17:48:52 | 显示全部楼层
    谢谢楼主的分享
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    开心
    2016-3-28 19:47
  • 签到天数: 1 天

    [LV.1]初来乍到

    发表于 2016-3-28 20:10:49 | 显示全部楼层
    混个脸熟
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    发表于 2016-3-29 03:25:54 | 显示全部楼层
    支持,看起来还是可以的
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    慵懒
    2019-4-14 17:44
  • 签到天数: 5 天

    [LV.2]偶尔看看I

    发表于 2016-3-29 08:28:56 | 显示全部楼层
    支持中国红客联盟(ihonker.org)
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    发表于 2016-3-29 16:08:51 | 显示全部楼层
    我是来水经验的……
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    发表于 2016-3-30 11:42:27 | 显示全部楼层
    谢谢楼主的分享
    回复 支持 反对

    使用道具 举报

    您需要登录后才可以回帖 登录 | 注册

    本版积分规则

    快速回复 返回顶部 返回列表