iOS Mail 客户端漏洞很可能已经被远程利用
2020-05-13 11:26:14 Author: www.4hou.com(查看原文) 阅读量:344 收藏

1.png

在ZecOps 团队宣布在iOS的默认邮件应用程序中发现RCE漏洞之后,已经有很多用户联系了他们,他们怀疑自己成为了这个漏洞的攻击目标。

在这篇文章中,我们将介绍一种简单的方法来喷洒堆,通过这种方法,我们可以证明远程利用这个漏洞是可能的。除此之外,我们还将提供两个在野外观察到的触发器示例。

目前,我们已经发现了该漏洞具有以下攻击性能:

1.邮件应用程序中的远程堆溢出;

2.能够通过传入邮件由攻击者控制的输入内容来远程触发漏洞;

3.改变代码执行的能力;

4.事实提升访问内核的权限;

不过,我们并没有发现该漏洞可以泄漏消息,但让人感到惊讶是,信息泄漏并不是存在于邮件中,而是存在于其他过程中。因为dyld_shared_cache是通过大多数进程共享的,因此信息泄漏漏洞不一定必须存在于MobileMail中,例如iMessage的CVE-2019-8646也可以远程实现这个功能,这就打开了额外的攻击面(Facetime、其他应用、iMessage等)。本文,我们会远程利用这个漏洞所具有的所有特性。尽管如此,我们还是要做以下说明:

1.我们无意公开LPE,它允许我们在需要时对A12及更高版本的设备执行文件系统提取或内存检查。你可以在FreeTheSandbox.org 上了解更多关于移动设备的漏洞信息。

2.我们还没有在野外看到对本地特权升级(LPE)漏洞的利用;

我们还将分享我们在野外看到的两个触发器示例,并让你做出自己的推断和结论。

MailDemon赏金

最后,对于那些能够证明他们遭到攻击的示例,我们将提供赏金。

3.png

利用MailDemon

如前所述,MailDemon是一个很好的利用对象,因为它覆盖了MALLOC_NANO内存区域的模块,而MALLOC_NANO内存区域存储了大量的Objective-C对象。因此,它允许攻击者操纵已被攻击对象的ISA指针(允许他们引起类型混淆)或重写函数指针来控制进程的代码流,这是接管受影响过程的可行方法。

堆喷和堆整理技术

为了控制代码流,需要进行堆喷射以将制作的数据放入内存中。使用包含“dealloc”方法的伪方法缓存的伪造类,我们可以使用此方法触发漏洞后控制程序计数器(PC)寄存器。

下面是测试POC时生成的部分崩溃日志:

Exception Type:  EXC_BAD_ACCESS (SIGBUS)
Exception Subtype: EXC_ARM_DA_ALIGN at 0xdeadbeefdeadbeef
VM Region Info: 0xdeadbeefdeadbeef is not in any region.  Bytes after previous region: 16045690973559045872  
      REGION TYPE                      START - END             [ VSIZE] PRT/MAX SHRMOD  REGION DETAIL
      MALLOC_NANO            0000000280000000-00000002a0000000 [512.0M] rw-/rwx SM=PRV  
--->  
      UNUSED SPACE AT END
 
Thread 18 name:  Dispatch queue: com.apple.CFNetwork.Connection
Thread 18 Crashed:
0   ???                               0xdeadbeefdeadbeef 0 + -2401053088876216593
1   libdispatch.dylib                 0x00000001b7732338 _dispatch_lane_serial_drain$VARIANT$mp  + 612
2   libdispatch.dylib                 0x00000001b7732e74 _dispatch_lane_invoke$VARIANT$mp  + 480
3   libdispatch.dylib                 0x00000001b773410c _dispatch_workloop_invoke$VARIANT$mp  + 1960
4   libdispatch.dylib                 0x00000001b773b4ac _dispatch_workloop_worker_thread  + 596
5   libsystem_pthread.dylib           0x00000001b796a114 _pthread_wqthread  + 304
6   libsystem_pthread.dylib           0x00000001b796ccd4 start_wqthread  + 4
 
 
Thread 18 crashed with ARM Thread State (64-bit):
    x0: 0x0000000281606300   x1: 0x00000001e4b97b04   x2: 0x0000000000000004   x3: 0x00000001b791df30
    x4: 0x00000002827e81c0   x5: 0x0000000000000000   x6: 0x0000000106e5af60   x7: 0x0000000000000940
    x8: 0x00000001f14a6f68   x9: 0x00000001e4b97b04  x10: 0x0000000110000ae0  x11: 0x000000130000001f
   x12: 0x0000000110000b10  x13: 0x000001a1f14b0141  x14: 0x00000000ef02b800  x15: 0x0000000000000057
   x16: 0x00000001f14b0140  x17: 0xdeadbeefdeadbeef  x18: 0x0000000000000000  x19: 0x0000000108e68038
   x20: 0x0000000108e68000  x21: 0x0000000108e68000  x22: 0x000000016ff3f0e0  x23: 0xa3a3a3a3a3a3a3a3
   x24: 0x0000000282721140  x25: 0x0000000108e68038  x26: 0x000000016ff3eac0  x27: 0x00000002827e8e80
   x28: 0x000000016ff3f0e0   fp: 0x000000016ff3e870   lr: 0x00000001b6f3db9c
    sp: 0x000000016ff3e400   pc: 0xdeadbeefdeadbeef cpsr: 0x60000000

在这种示例下,堆喷射的理想原语是可以从远程触发的内存泄漏漏洞,因为我们希望所喷洒的内存在触发内存破坏之前保持不变。另一种方法是使用MFMutableData本身,当MFMutableData的大小小于0x20000字节时,它从堆中分配内存,而不是创建一个文件来存储内容。我们可以通过将电子邮件的内容分割成小于0x20000字节的行来控制MFMutableData的大小,因为IMAP库是按行读取电子邮件内容的。使用这个原语,我们有更好的机会将有效载荷放置到我们想要的地址中。

5.png

触发过程

一个过大的电子邮件能够复制漏洞作为一个PoC ,但是要获得稳定的利用,我们需要仔细研究“-[MFMutableData appendBytes:length:]“。

-[MFMutableData appendBytes:length:] 
{
  int old_len = [self length];
  //...
  char* bytes = self->bytes;
  if(!bytes){
     bytes = [self _mapMutableData]; //Might be a data pointer of a size 8 heap
  }
  copy_dst = bytes + old_len;
  //...
  memmove(copy_dst, append_bytes, append_length); // It used append_length to copy the memory, causing an OOB writing in a small heap
}

memove的目标地址是 ”bytes + old_len”,而不是“bytes”。那么,如果在触发漏洞之前我们积累了太多数据该怎么办?考虑到MALLOC_NANO区域的大小为512MB, “old_len”将以一个非常大的值结束,因此目标地址将以超出该区域边界的无效地址结束并立即崩溃。

7.png

为了减少“填充”的大小,我们需要在触发漏洞之前消耗尽可能多的数据。此时,内存泄漏就会必然发生。

值得注意的是,“填充”并不意味着溢出地址是完全随机的,由于硬件大小相同,因此硬件模型可以预测“填充”,因为在我们的测试中,相同大小的mmap通常会失败。

崩溃分析

这篇文章讨论了在以前的文章中介绍的在野外检测到的MobileMail漏洞的几种触发因素和可利用性。

示例1显示,该漏洞在被披露之前就在野外被触发。

示例2是由于MALLOC_NANO区域中的内存损坏,损坏的内存的值是已发送电子邮件的一部分,并完全由发件人控制。

示例1

当发生溢出时,易受攻击的函数内部立即触发了以下崩溃。

Coalition:           com.apple.mobilemail [521]
 
Exception Type:  EXC_BAD_ACCESS (SIGSEGV)
Exception Subtype: KERN_INVALID_ADDRESS at 0x000000004a35630e //[a]
VM Region Info: 0x4a35630e is not in any region.  Bytes before following region: 3091946738
      REGION TYPE                      START - END             [ VSIZE] PRT/MAX SHRMOD  REGION DETAIL
      UNUSED SPACE AT START
--->  
      __TEXT                 000000010280c000-0000000102aec000 [ 2944K] r-x/r-x SM=COW  ...p/MobileMail]
 
 
Thread 4 Crashed:
0   libsystem_platform.dylib          0x00000001834a5a80 _platform_memmove  + 208
       0x1834a5a74         ldnp x10, x11, [x1, #16]       
       0x1834a5a78         add x1, x1, 0x20               
       0x1834a5a7c         sub x2, x2, x5                 
       0x1834a5a80         stp x12, x13, [x0]   //[b]          
       0x1834a5a84         stp x14, x15, [x0, #16]        
       0x1834a5a88         subs x2, x2, 0x40              
       0x1834a5a8c         b.ls 0x00002ab0    
 
1   MIME                              0x00000001947ae104 -[MFMutableData appendBytes:length:]  + 356
2   Message                           0x0000000194f6ce6c -[MFDAMessageContentConsumer consumeData:length:format:mailMessage:]  + 804
3   DAEAS                             0x000000019ac5ca8c -[ASAccount folderItemsSyncTask:handleStreamOperation:forCodePage:tag:withParentItem:withData:dataLength:]  + 736
4   DAEAS                             0x000000019aca3fd0 -[ASFolderItemsSyncTask handleStreamOperation:forCodePage:tag:withParentItem:withData:dataLength:]  + 524
5   DAEAS                             0x000000019acae338 -[ASItem _streamYourLittleHeartOutWithContext:]  + 440
6   DAEAS                             0x000000019acaf4d4 -[ASItem _streamIfNecessaryFromContext:]  + 96
7   DAEAS                             0x000000019acaf758 -[ASItem _parseNextValueWithDataclass:context:root:parent:callbackDict:streamCallbackDict:parseRules:account:]  + 164
8   DAEAS                             0x000000019acb001c -[ASItem parseASParseContext:root:parent:callbackDict:streamCallbackDict:account:]  + 776
9   DAEAS                             0x000000019acaf7d8 -[ASItem _parseNextValueWithDataclass:context:root:parent:callbackDict:streamCallbackDict:parseRules:account:]  + 292
10  DAEAS                             0x000000019acb001c -[ASItem parseASParseContext:root:parent:callbackDict:streamCallbackDict:account:]  + 776
...
 
Thread 4 crashed with ARM Thread State (64-bit):
    x0: 0x000000004a35630e   x1: 0x00000001149af432   x2: 0x0000000000001519   x3: 0x000000004a356320
    x4: 0x0000000100000028   x5: 0x0000000000000012   x6: 0x0000000c04000100   x7: 0x0000000114951a00
    x8: 0x44423d30443d3644   x9: 0x443d30443d38463d  x10: 0x3d31413d31443d30  x11: 0x31413d31463d3444
   x12: 0x33423d30453d3043  x13: 0x433d30443d35423d  x14: 0x3d30443d36443d44  x15: 0x30443d38463d4442
   x16: 0x00000001834a59b0  x17: 0x0200080110000100  x18: 0xfffffff00a0dd260  x19: 0x000000000000152b
   x20: 0x00000001149af400  x21: 0x000000004a35630e  x22: 0x000000004a35630f  x23: 0x0000000000000008
   x24: 0x000000000000152b  x25: 0x0000000000000000  x26: 0x0000000000000000  x27: 0x00000001149af400
   x28: 0x000000018dbd34bc   fp: 0x000000016da4c720   lr: 0x00000001947ae104
    sp: 0x000000016da4c720   pc: 0x00000001834a5a80 cpsr: 0x80000000

对于[a]和[b],我们知道进程在“memmove”中崩溃,这个进程被“-[MFMutableData appendBytes:length:]”调用,这意味着“copy_dst”的值首先是一个无效地址,即0x4a35630e。

那么寄存器x0 (0x4a35630e)的值是从哪里来的呢?因为,它比最低有效地址小得多。

结果是,当在mmap文件失败后,同时分配8字节内存失败时,进程就会崩溃。

无效地址0x4a35630e实际上是触发漏洞之前MFMutableData的长度偏移量(即“old_len”)。当calloc分配内存失败时,它返回NULL,因此copy_dst将是“0 + old_len(0x4a35630e)”。

在本例中,“old_len”约为1.2GB,这与POC的平均长度相匹配,这可能会导致mmap失败并触发漏洞。

请注意,x8-x15和x0完全由发送者控制。

这次崩溃为我们的上述问题(如果我们在触发漏洞之前积累了太多的数据,会怎么样?)提供了另一个答案,8字节内存的分配可能会失败并崩溃,而将有效载荷复制到一个无效的地址。这可能使可靠的利用变得更加困难,因为我们可能在接管程序计数器之前崩溃。

回顾2010年iOS 3.1.3中的神秘触发!

值得注意的是,我们在modmy.com论坛上找到了一个匿名用户完全类似的触发事件的公开示例:

漏洞版本:iPhone 2G上的iOS 3.1.3;

发生时间:2010年10月22日;

用户“shyamsandeep”于2008年6月12日注册,最后一次登录是在2011年10月16日,在论坛中只有一篇帖子,其中就包含了这个触发事件。

这个崩溃的r0等于0x037ea000,这可能是我们在之前的文章中披露的第一个漏洞,这是由于ftruncate()失败造成的。有趣的是,正如我们在第一种示例中所解释的,它也可能是分配8字节内存失败的结果,但是由于日志缺少内存区域信息,因此无法确定确切原因。但是,可以肯定的是,自2010年以来,这个可利用漏洞的触发因素很多。

Identifier: MobileMail
Version: ??? (???)
Code Type: ARM (Native)
Parent Process: launchd [1]
 
Date/Time: 2010-10-22 08:14:31.640 +0530
OS Version: iPhone OS 3.1.3 (7E18)
Report Version: 104
 
Exception Type: EXC_BAD_ACCESS (SIGSEGV) Exception Codes: KERN_INVALID_ADDRESS at 0x037ea000 Crashed Thread: 4
Thread 4 Crashed:
0 libSystem.B.dylib 0x33aaef3c 0x33aad000 + 7996 //memcpy + 0x294
1 MIME 0x30a822a4 0x30a7f000 + 12964 //_FastMemoryMove + 0x44
2 MIME 0x30a8231a 0x30a7f000 + 13082 // -[MFMutableData appendBytes:length:] + 0x6a
3 MIME 0x30a806d6 0x30a7f000 + 5846 // -[MFMutableData appendData:] + 0x32
4 Message 0x342e2938 0x34251000 + 596280 // -[DAMessageContentConsumer consumeData:length:format:mailMessage:] + 0x25c
5 Message 0x342e1ff8 0x34251000 + 593912 // -[DAMailAccountSyncConsumer consumeData:length:format:mailMessage:] +0x24
6 DataAccess 0x34146b22 0x3413e000 + 35618 // -[ASAccount
folderItemsSyncTask:handleStreamOperation:forCodePage:tag:withParentItem:withData:dataLength:] + 0x162
7 DataAccess 0x3416657c 0x3413e000 + 165244 //[ASFolderItemsSyncTaskhandleStreamOperation:forCodePage:tag:withParentIt em:withData:dataLength:] + 0x108
...
 
Thread 4 crashed with ARM Thread State:
r0: 0x037ea000 r1: 0x008729e0 r2: 0x00002205 r3: 0x4e414153
r4: 0x41415367 r5: 0x037e9825 r6: 0x00872200 r7: 0x007b8b78
r8: 0x0001f825 r9: 0x001fc098 r10: 0x00872200 r11: 0x0087c200
ip: 0x0000068a sp: 0x007b8b6c lr: 0x30a822ab pc: 0x33aaef3c
cpsr: 0x20000010

示例2

以下是在收到并处理电子邮件之后发生的另一次崩溃:

Coalition:           com.apple.mobilemail [308]
 
Exception Type:  EXC_BAD_ACCESS (SIGSEGV)
Exception Subtype: KERN_INVALID_ADDRESS at 0x0041004100410041 // [a]
VM Region Info: 0x41004100410041 is not in any region.  Bytes after previous region: 18296140473139266  
      REGION TYPE                      START - END             [ VSIZE] PRT/MAX SHRMOD  REGION DETAIL
      mapped file            00000002d31f0000-00000002d6978000 [ 55.5M] r--/rw- SM=COW  ...t_id=9bfc1855
--->  
      UNUSED SPACE AT END
 
Thread 13 name:  Dispatch queue: Internal _UICache queue
Thread 13 Crashed:
0   libobjc.A.dylib                   0x00000001b040fca0 objc_release  + 16
       0x1b040fc94         mov x29, sp                    
       0x1b040fc98         cbz x0, 0x0093fce4             
       0x1b040fc9c         tbnz x0, #63, 0x0093fce4       
       0x1b040fca0         ldr x8, [x0]            // [b]       
       0x1b040fca4         and x8, x8, 0xffffffff8        
       0x1b040fca8         ldrb w8, [x8, #32]             
       0x1b040fcac         tbz w8, #2, 0x0093fd14         
 
1   CoreFoundation                    0x00000001b1119408 -[__NSDictionaryM removeAllObjects]  + 600
2   libdispatch.dylib                 0x00000001b0c5d7d4 _dispatch_client_callout  + 16
3   libdispatch.dylib                 0x00000001b0c0bc1c _dispatch_lane_barrier_sync_invoke_and_complete  + 56    
4   UIFoundation                      0x00000001bb9136b0 __16-[_UICache init]_block_invoke  + 76     
5   libdispatch.dylib                 0x00000001b0c5d7d4 _dispatch_client_callout  + 16
6   libdispatch.dylib                 0x00000001b0c0201c _dispatch_continuation_pop$VARIANT$mp  + 412
7   libdispatch.dylib                 0x00000001b0c11fa8 _dispatch_source_invoke$VARIANT$mp  + 1308
8   libdispatch.dylib                 0x00000001b0c0ee00 _dispatch_kevent_worker_thread  + 1224   
9   libsystem_pthread.dylib           0x00000001b0e3e124 _pthread_wqthread  + 320          
10  libsystem_pthread.dylib           0x00000001b0e40cd4 start_wqthread  + 4 
 
 
Thread 13 crashed with ARM Thread State (64-bit):
    x0: 0x0041004100410041   x1: 0x00000001de1ac18a   x2: 0x0000000000000000   x3: 0x0000000000000010
    x4: 0x00000001b0c60388   x5: 0x0000000000000010   x6: 0x0000000000000000   x7: 0x0000000000000000
    x8: 0x0000000281f94090   x9: 0x00000001b143f670  x10: 0x0000000142846800  x11: 0x0000004b0000007f
   x12: 0x00000001428468a0  x13: 0x000041a1eb487861  x14: 0x0000000283ed9d10  x15: 0x0000000000000004
   x16: 0x00000001eb487860  x17: 0x00000001b11191b0  x18: 0x0000000000000000  x19: 0x0000000281dce4c0
   x20: 0x0000000282693398  x21: 0x0000000282693330  x22: 0x0000000000000000  x23: 0x0000000000000000
   x24: 0x0000000281dce4c8  x25: 0x000000000c000000  x26: 0x000000000000000d  x27: 0x00000001eb48e000
   x28: 0x0000000282693330   fp: 0x000000016b8fe820   lr: 0x00000001b1119408
    sp: 0x000000016b8fe820   pc: 0x00000001b040fca0 cpsr: 0x20000000

[a]:对象的指针被“0x00410041004100410041”覆盖,它在unicode中是AAAA。

[b]是我们为更好地理解而添加的关于崩溃地址的指令之一,当-[nsdictionarym removeAllObjects]试图释放一个对象时,进程在指令“ldr x8, [x0]”上崩溃。

通过逆向工程-[nsdictionarym removeAllObjects],我们可以理解寄存器x0是从x28(0x0000000282693330)加载的,因为在崩溃之前,寄存器x28从未被更改过。

11.png

让我们看一下x28: 0x0000000282693330的虚拟内存区域信息,覆盖的对象存储在MALLOC_NANO区域,该区域存储小堆块。堆溢出漏洞会破坏同一个区域,因为它会溢出一个8字节的堆块,这个堆块也存储在MALLOC_NANO中。

MALLOC_NANO              0x0000000280000000-0x00000002a0000000     rw-/rwx

这个崩溃实际上非常接近于控制PC,因为它控制了Objective-C对象的指针。通过将寄存器x0的值指向一个带有伪对象和伪方法缓存的类的内存,攻击者可以控制PC指针。

总结

1.很少看到用户提供的输入触发和控制远程漏洞;

2.如上所述,利用这个漏洞是可能的;

3.如上所述,现实中的触发器具有较大的分配值;

4.如上所述,现实中的触发器的值是由发送方控制的;

5.我们寻找的电子邮件丢失/删除了;

6.这个漏洞在2010年的iPhone 2G设备上就有了;

苹果如何改进日志?

iOS日志中缺少详细信息,而且缺少为个人和组织选择数据粒度的选项,因此需要进行更改,以使iOS能够与MacOS、Linux和Windows功能相媲美。总的来说,为了分析手机是如何被入侵的而侵入手机的做法是完全错误的,但却是迫不得已。

为此,我们建议苹果改进其漏洞诊断流程,以帮助个人、组织和软件开发者调查他们的设备。我们的建议如下:

1.改进崩溃:启用查看每个指针/寄存器旁边的内存的功能

2.改善崩溃:显示堆栈/堆内存/寄存器附近的内存;

3.将PID / PPID / UID / EUID添加到所有适用的事件;

4.无需物理连接即可将这些日志发送到远程服务器,在多个示例中,日志被神秘地删除;

5.能够对可疑的iOS设备进行完整的数字取证分析,而不需要先侵入设备;

本文翻译自:https://blog.zecops.com/vulnerabilities/seeing-maildemons-technique-triggers-and-a-bounty/ 如若转载,请注明原文地址


文章来源: https://www.4hou.com/posts/GgvQ
如有侵权请联系:admin#unsafe.sh