Apple macOS 10.13.2 – Double mach_port_deallocate in kextd due to Failure to Comply with MIG Ownership Rules

  • 作者: Google Security Research
    日期: 2018-04-30
  • 类别:
    平台:
  • 来源:https://www.exploit-db.com/exploits/44561/
  • Here's a kextd method exposed via MIG (com.apple.KernelExtensionServer)
    
    kern_return_t _kextmanager_unlock_kextload(
    mach_port_t server,
    mach_port_t client)
    {
    kern_return_t mig_result = KERN_FAILURE;
    
    if (gClientUID != 0) {
    OSKextLog(/* kext */ NULL,
    kOSKextLogErrorLevel | kOSKextLogIPCFlag,
    "Non-root kextutil doesn't need to lock/unlock.");
    mig_result = KERN_SUCCESS;
    goto finish;
    }
    
    if (client != (mach_port_t)dispatch_source_get_handle(_gKextutilLock)) {
    OSKextLog(/* kext */ NULL,
    kOSKextLogErrorLevel | kOSKextLogIPCFlag,
    "%d not used to lock for kextutil.", client);
    goto finish;
    }
    
    removeKextutilLock();
    
    mig_result = KERN_SUCCESS;
    
    finish:
    // we don't need the extra send right added by MiG
    mach_port_deallocate(mach_task_self(), client);
    
    return mig_result;
    }
    
    If the client has UID 0 but passes an invalid client port this code will
    drop a UREF on client port then return KERN_FAILURE.
    
    Returning KERN_FAILURE in MIG means all resources will be released which will
    cause client to be passed to mach_port_deallocate again, even though only 
    one UREF was taken.
    
    You'll have to use a debugger attached to kextd to see this behaviour.
    
    This class of bug is exploitable; please see the writeup for mach_portal from 2016
    where I exploited a similar issue [https://bugs.chromium.org/p/project-zero/issues/detail?id=959]
    The TL;DR is that an attacker can drop an extra UREF on any send rights in kextd for which the
    attacker also has a send right; you could use this to cause a name for a privileged service
    to be deallocated then cause the name to be reused to name a port you control.
    
    Exploitation of this would be a privesc from unentitled root to root with
    com.apple.rootless.kext-management and com.apple.rootless.storage.KernelExtensionManagement entitlements,
    which at least last time I looked was equal to kernel code execution.
    
    tested on MacOS 10.13.2
    
    
    Proof of Concept:
    https://gitlab.com/exploit-database/exploitdb-bin-sploits/-/raw/main/bin-sploits/44561.zip