详解iOS零点击无线电近程漏洞(一)

匿名者  165天前

注意:这个漏洞问题已经在2020年5月iOS 13.5推出Privacy-PreservingContact Tracing功能之前得到了相应的修复。

https://youtu.be/ikZTNSmbh00

在这个演示视频中,我远程触发了一个无需身份验证的内核内存损坏漏洞,导致位于无线电范围内的所有iOS设备重启,并且全程无需用户进行交互。在接下来的长达3万字的篇幅中,我们将详细介绍从这个基本演示到成功利用这个漏洞的完整过程;攻击者成功利用这个漏洞后,就能在附近的iOS设备上运行任意代码并窃取所有用户数据。

简介

下面这句话摘自@halvarflake在2020年2月的Offensivecon大会上的主题演讲:

“漏洞利用是我们在现实世界中所体验过的最接近于“魔法咒语”的东西:只要构建正确的咒语,就能魔法般地远程控制设备。”

在2020年的半年时间里,我一直蜗居在卧室里:周围是我可爱的、大声尖叫的孩子们,我则埋头研究自己的魔法咒语。不过可惜的是,这并不是一个能让孩子们每天早上睡到9点的咒语,而是一个可蠕虫化的无线电进程漏洞——利用这个漏洞,我能够完全控制自己周围的所有iPhone设备:不仅可以查看设备中所有的照片,阅读所有的电子邮件,复制所有的私人信息,并能实时监控设备中的一切。

这个项目的结果不应该是:没有人会浪费六个月的时间来黑我的手机,我很欣慰。相反,它应该是:一个人在自己的卧室里独自修炼,并获得了一种超能力:能够入侵附近的所有iPhone用户。

想象一下,拥有这种能力的攻击者一定会滋生让人膨胀的掌控感。随着人们把越来越多的时间和精力投入到这些设备上,因此,攻击者肯定能从一个毫无戒备的攻击目标那里获得大量的用户信息。

更重要的是,借助于定向天线、更高的发射功率和更敏感的接收器,这种攻击的范围将越来越远。

当然,这些漏洞并不是从在野漏洞样本中发现的;相反,这些漏洞是我自己是通过手动逆向分析找到的。但我们确实知道,漏洞供应商似乎已经盯上了这些修复措施。例如,就拿澳大利亚的“市场领先的信息安全企业”Azimuth Security的联合创始人Mark Dowd发布的推文来说吧:

1.png      

@mdowd在2020年5月27日发布的推文提到:可以通过AWDL触发BSS的DoubleFree漏洞

Mark在这里提到的漏洞,就是我向苹果公司报告的漏洞之一。如果对这段特定的代码没有浓厚的兴趣,他就根本不会注意到这个修复。

2018年的这篇Vice文章对Azimuth进行了很好的概述,并解释了他们为什么会对这类漏洞感兴趣。您可能觉得Azimuth的客户也许都是“好人”,可是既便如此,那又如何?!未打补丁的漏洞并不像物理意义的东西,只能被一方占有。每个人都可以利用未修补的漏洞,同时,Mark Dowd也并非唯一一个在推特上谈论AWDL漏洞的人。

在我从事过的单一漏洞研究项目中,它是耗时最长的,大约花了半年时间。但有必要事先强调的是,全球网络武器供应商团队和公司一般并非单兵作战。他们资源丰富且善于和专家协作,这些专家各有所长。他们绝非不了解蓝牙或WiFi工作原理的新手。他们还可能具备我无法拥有的访问信息和硬件的权限,如访问开发设备、特殊电缆、被泄露的源代码、符号文件等等。

当然,iPhone的设计初衷,并不希望有人获得这种超能力。那么,是什么地方出了问题,以至于出现这种情况呢?不幸的是,这说起来话就长了:在内核用于解析不受信任的数据的C++代码中存在一个很小的缓冲区溢出漏洞,并且暴露给了远程攻击者。

事实上,整个exploit只是利用了一个内存损坏漏洞,就成功入侵了旗舰版的iPhone 11 Pro设备。仅凭这一个安全问题,我就能击垮所有的缓解措施,从而远程获得本机代码执行和内核内存读写能力。

相对于大型科技公司的这些代码库的规模和复杂性来说,专门负责主动审计其产品的源代码以寻找漏洞的安全团队的规模还是太小了。Android和iOS系统都是完全自定义的技术堆栈。在这些堆栈中,不仅存在内核和设备驱动程序,还存在几十个攻击者可以接触到的应用程序、几百个服务和几千个运行在具有定制硬件和固件的设备上的程序库。

实际上,要想全面审计所有的代码,包括每一行新加入的代码和几十年来的遗留代码,那是不切实际的——至少在技术领域常见的资源划分情况下是不现实的,因为安全工程师和开发人员的比例可能是1:20、1:40,甚至更高。

为了应对这一不可逾越的挑战,安全团队正确地将重点放在了对新功能的设计层面的审查上。这是非常明智的做法:在设计阶段就把事情做好,可以将错误和漏洞(这些都是不可避免的)的影响降至最低。例如,确保像GPU这样的新硬件外围设备只能访问物理内存的有限部分,即使它们被攻击者攻陷,也可以将影响降至最低。这样的话,攻击者只能寄希望于寻找额外的漏洞来“延长漏洞利用链”,也就是说,为了成功入侵一台设备,将不得不利用越来越多的漏洞。反过来讲,如果要对已经交付的功能进行这样的约束的话,很多时候是不可能的;就算能这样做的话,也会困难得多。

除了进行设计层面的审查外,安全团队还可以通过限制攻击者能够利用漏洞所做的事情来解决其产品的复杂性。当然,这些就属于缓解措施了。实际上,缓解措施又可以分为通用型缓解措施,如堆栈cookie,以及针对特定应用的缓解措施,如javascriptCore中的Structure ID。不过,缓解措施所能提供的保护功能,通常比设计层面的保护功能要弱一些,但是它们的目标是一致的:“延长漏洞利用链”,以迫使攻击者寻找新的漏洞,从而付出更多的努力。

第三种被防御团队广泛使用的方法是模糊测试,它试图通过蛮力方式模仿攻击者的漏洞挖掘过程。对于模糊测试技术,经常被误解为是一种只能发现容易找到的漏洞或“低垂的果实”的有效方法。实际上,更为准确的描述是,模糊测试是一种能够挖掘易于进行模糊测试的漏洞的有效方法。为什么这么说呢?因为许多在熟练的漏洞研究者眼中是低垂的果实的漏洞,要想找到它们,通常需要达到一个程序点,而现在的fuzzer无论耗费多少计算资源都无法抵达这些地方。

对于各大技术公司(当然不仅限于苹果公司)而言,它们的问题在于,尽管进行了设计审查,采取了缓解措施并进行了模糊测试,但是这些对于构建安全的代码库来说只是必需的,却远远不够。

众所周知,虽然Fuzzer无法像熟练的漏洞研究者那样对代码进行推理,但是,有了它们,人们不用殚精竭虑,就能低成本地找到许多的安全漏洞。在过去的几年里,我的一个工作重点,就是让人们认识到iOS代码库就像其他主要的现代操作系统一样,也具有很高的漏洞密度。不仅如此,它还具有高密度的“优质漏洞”,也就是能够创造强大的“幽灵机器(Weird Machines)”的漏洞。

这种“优质漏洞”的概念是进攻性研究人员凭直觉就能理解的,但对于那些没有漏洞利用背景的人来说,可能就很难理解了。Thomas Dullien的幽灵机器论文为幽灵机器的概念及其对漏洞利用的适用性提供了最好的阐释。假设一个足够复杂的状态机需要处理攻击者控制的输入,那么所谓的“优质漏洞”,就是能够将攻击者控制的输入变成“代码”的漏洞;也就是说,“优质漏洞”能够通过引入一个新的、非预期的状态转换机制,从而获得一个新的、非预期的状态机。这样的话,漏洞利用的艺术就变成了确定如何利用漏洞来引入足够强大的、新的状态转换机制的艺术,这样,作为终极目标,攻击者提供的输入最终将变成一个新的、能够进行任意系统交互的幽灵机器代码。

一旦这种幽灵机器出现,缓解措施就会形同虚设;即使缓解措施的实现毫无破绽,通常也不是强大的幽灵机器的对手。因此,寻找漏洞的攻击者会专门寻找幽灵机器原语。他们的审计过程专注于特定的攻击面和特定的漏洞类型。这与需要考虑所有可能的攻击面和所有漏洞类型的产品安全团队形成了鲜明的对比。

就目前情况而言,到2020年11月为止,我相信对于一个锐意进取的攻击者来说,即使手里只有一个漏洞,仍然有可能构造一台功能强大的幽灵机器,强大到完全可以远程入侵iPhone。实际上,该过程中最难的部分,可能并不是我们通常认为最难的事情,至少在您不了解幽灵机器的情况下通常都是如此。

通常来说,漏洞挖掘的数量和质量仍然与投入的时间成正比。能否击败缓解措施,关键是看能否构建出足够强大的幽灵机器。具体来说,指针验证码(PAC)的出现意味着已经无法通过简单的程序计数器控制以及ROP或JOP来直接访问功能强大的幽灵机器。取而代之的是,攻击者首先需要建立了一个远程任意内存读写原语,它实际中同样非常强大,而当前的PAC实现(几乎完全专注于限制控制流)并不是为了缓解这种影响而设计的。

实际上,无论多么安全的系统设计也无法挽救局面,因为在制造可及时交付的产品过程中不可避免地需要进行折衷。这样一个驱动多个复杂状态机的复杂解析器是否真的应该在内核上下文中处理不受信任的远程输入吗?在理想情况下,当然是不应该的;并且几乎可以肯定的是,应该在设计审查中就将其标记出来。但是对于这个特殊的功能来说,是有严格的时间限制的,这意味着隔离分析器可不是一件容易的事情。当然,也不是说无法做到,但却是一个重大工程挑战,远远超出了这个功能本身的范畴。归根结底,手机卖的就功能,而该功能无疑是非常酷的;所以,尽管存在风险,但仍然做出采用这种设计的决定,这一点都不难理解。

但是,存在风险意味着如果事情没有按照预期发展,就会带来不良后果。当涉及到软件漏洞时,可能很难将那些被接受的风险和后果联系在一起。我不知道我是否是唯一发现这些漏洞的人,尽管我是第一个向苹果通知这些漏洞并与苹果进行合作来修复漏洞的人。在接下来的3万字中,将向大家展示我到底能利用这个攻击面中的一个漏洞做些什么,并希望本文能让大家对幽灵机器的威力的认识上一个新的台阶。

我并不认为所有的希望都破灭了,只是还有更多的事情要做。在结论部分中,我将分享一些自己的看法,也许对打造更安全的iPhone有所裨益。

如果你想继续关注这个漏洞,可以在ProjectZero问题跟踪器中找到附在问题1982上的详细信息。

安全漏洞的发现过程

2018年,苹果发布了一个iOS测试版,但是并没有从kernelcache中剥离函数名称符号。虽然这几乎可以肯定是一个失误,但像这样的事件却能给安全研究人员带来很大的帮助。我喜欢的消遣方式之一,就是浏览这个庞大的符号列表,以及随意阅读几段汇编代码。有一天,当我利用IDA翻阅memmove函数的交叉引用时,虽然脑子里并没有特定的目标,却突然发现了一些值得仔细研究的东西:

1.png

当时,在IDA Pro的交叉引用窗口中,显示了对memmove函数的大量调用;并且,IO80211AWDLPeer::parseAwdlSyncTreeTLV中的一个调用点恰好被突出显示。

一旦知道了函数名称,就能为漏洞研究者填补大量的背景信息。对于研究人员来说,当面临一个完全剥离符号信息的、大小为30多MB的二进制blob时(如iOS的kernelcache),内心应该是崩溃的。这是因为,要想确定所有东西是如何组合在一起的,需要做大量的工作。哪些代码位会暴露给攻击者?哪些地方存在安全检查?代码的不同部分是在什么执行环境下运行的?这些疑问数不胜数。

就这里来说,这个特定的驱动程序在MacOS上也是可用的,而且函数名称符号并没有被剥离。

还有三件事情,让这个突出显示的函数引起了我的高度关注:

1) 函数的名称:

IO80211AWDLPeer::parseAwdlSyncTreeTLV

当时,我并不知道AWDL是什么。但我知道TLV(类型、长度、值)经常用来赋予数据以结构,解析一个TLV可能意味着它来自某个不受信任的地方。而80211则是一道送分题,表明可能与WiFi有关。看来这个函数很值得仔细研究。下面的代码来自Hex-Rays的原始反编译结果,我们稍后会进行梳理:

__int64 __fastcallIO80211AWDLPeer::parseAwdlSyncTreeTLV(__int64 this, __int64 buf)

{

  const void*v3; // x20

  _DWORD *v4; //x21

  int v5; // w8

  unsigned__int16 v6; // w25

  unsigned__int64 some_u16; // x24

  int v8; // w21

  __int64 v9; //x8

  __int64 v10; //x9

  unsigned__int8 *v11; // x21

 

  v3 = (constvoid *)(buf + 3);

  v4 = (_DWORD*)(this + 1203);

  v5 = *(_DWORD*)(this + 1203);

  if ( ((v5 + 1)& 0xFFFFu) <= 0xA )

    v6 = v5 + 1;

  else

    v6 = 10;

  some_u16 =*(unsigned __int16 *)(buf + 1) / 6uLL;

  if ((_DWORD)some_u16 == v6 )

  {

    some_u16 =v6;

  }

  else

  {

   IO80211Peer::logDebug(

      this,

     0x8000000000000uLL,

      "Peer%02X:%02X:%02X:%02X:%02X:%02X: PATH LENGTH error hc %u calc %u \n",

      *(unsigned__int8 *)(this + 32),

      *(unsigned__int8 *)(this + 33),

      *(unsigned__int8 *)(this + 34),

      *(unsigned__int8 *)(this + 35),

      *(unsigned__int8 *)(this + 36),

      *(unsigned__int8 *)(this + 37),

      v6,

      some_u16);

    *v4 =some_u16;

    v6 = some_u16;

  }

  v8 =memcmp((const void *)(this + 5520), v3, (unsigned int)(6 * some_u16));

  memmove((void*)(this + 5520), v3, (unsigned int)(6 * some_u16));

从上面的代码来看,肯定是在解析什么东西。同时,其中含有一些复杂的字节操作;还有一些看起来像边界检查和错误消息的东西。

2) 第二件引起我的兴趣的事情是错误信息字符串。

"Peer %02X:%02X:%02X:%02X:%02X:%02X: PATH LENGTHerror hc %u calc %u\n"

对我来说,任何一种LENGTH错误听起来都很让人着迷,尤其是在深入考察之后……

3) 控制流图

仔细阅读代码会发现,尽管日志消息包含单词“error”,但这里没有任何内容被视为错误条件。由此来看,IO80211Peer::logDebug并不是一个关键的日志API,相反,它只是用于记录消息字符串。通过追溯传递给memmove函数的参数length的值发现,无论采取哪种方法,我们最终都会得到一个来自输入缓冲区的u16值(向下取整为最接近的6的倍数),它是作为length参数传递给函数memmove的。

真的会这么简单吗?根据我的经验,通常情况下,真正的攻击面中这么浅的漏洞往往难成气候。通常来说,会在很远的地方进行某些长度检查;有时我们需要花上几天时间才能搞清楚为什么似乎无法接触到使用长度不当的代码,但是,找到后才发现,这原来是十年前的一个CVE漏洞。不过,还是值得一试的。

但是,这个攻击面到底是什么呢?

第一个概念验证

在谷歌上搜索了一下,我们了解到awdl不仅是威尔士诗歌中的一种,也是苹果公司专有的网状网络协议的缩写,该协议的全称是Apple Wireless Direct Link。它似乎用于AirDrop以及其他功能。

我们的第一个目标,是搞清楚是否真的可以远程触发这个漏洞。

从parseAwdlSyncTreeTLV方法中的强制类型转换可以看出,type-length-value对象首先使用了一个字节表示类型,然后两个字节表示长度,后面是有效载荷值。

在IDA中,选择函数名,然后进入View -> Open subviews -> Cross references (或直接按“x”键),结果表明:对于这个方法,IDA只找到了一个调用者:

IO80211AWDLPeer::actionfr ameReport

...

      case0x14u:

        if(v109[20] >= 2)

          gotoLABEL_126;

       ++v109[0x14];

       IO80211AWDLPeer::parseAwdlSyncTreeTLV(this, bytes);

所以0x14可能是类型值,而v109看起来可能是在计算这些TLV的数量。

在函数名称的列表中,我们还可以看到对应的BuildSyncTreeTlv方法。如果我们能让两台机器加入一个AWDL网络,我们是否可以在发送SyncTree TLV之前,直接使用MacOS内核调试器使其变得非常大么?

是的,的确可以。我使用两台MacOS笔记本,并在两台笔记本上都启用了AirDrop功能,然后使用内核调试器来编辑其中一台笔记本发送的SyncTree TLV,最终导致另一台笔记本由于memmove函数越界而引发内核崩溃。

如果您对上述过程的细节感兴趣,请参阅我在2019年11月29日向苹果公司提交的原始漏洞报告。这个漏洞于2020年1月28日在iOS 13.1.1/MacOS 10.15.3版本中得到了修复,其漏洞编号为CVE-2020-3843。

实际上,我们的旅程才刚刚开始。从这里开始,到无需用户交互的情况下在iPhone 11 Pro上远程执行代码,还有很长的路要走……

现有技术

德国TU Darmstadt大学的安全移动网络实验室(也称为SEEMOO)曾发表过关于AWDL的系列论文。为了撰写这些论文,该实验室的研究人员进行了大量的逆向工程(除此之外,他们还有机会接触到一些泄露的Broadcom源代码);对于理解AWDL来说,这些论文都是非常宝贵的,而且几乎是目前唯一的资源。

在第一篇论文《One Billion Apples’ Secret Sauce: Recipe for the Apple Wireless Direct Link Ad hocProtocol》中,详细介绍了AWDL使用的帧格式和信道跳变机制的原理。

第二篇论文《A Billion OpenInterfaces for Eve and Mallory: MitM, DoS, and Tracking Attacks on iOS andmacOS Through Apple Wireless Direct Link》,则更侧重于Airdrop功能(Airdrop是建立在AWDL之上的操作系统功能之一)。此外,这篇论文还研究了Airdrop如何使用蓝牙低功耗广播技术来启用其他设备上的AWDL接口。

此外,该研究小组还编写了一个名为OWL(Open Wireless Link)的开源AWDL客户端。虽然我无法让OWL正常工作,但它还是一个宝贵的参考资料,我确实借鉴了其中的某些框架定义。

什么是AWDL?

AWDL是一个苹果公司专有的网状网络协议,旨在让iPhone、iPad、Mac和Apple Watch等苹果设备形成临时的点对点网状网络。如果您拥有一台苹果设备,那么,一天之内可能会多次创建或连接到这些临时的网状网络,尽管可能意识不到这一点。

如果您曾经使用过Airdrop功能,通过Airplay将音乐流式传输到你的HomePod或Apple TV上,或者将Sidecar用作iPad的辅助显示屏,那么就可以肯定:您一直在用AWDL。即使您没有使用这些功能,但是附近的人一直在使用的话,那么您的设备也很有可能加入他们的AWDL网状网络。

需要注意的是,AWDL并不是一个自定义的无线电协议;无线电层是WiFi(特别是802.11g和802.11a)。

大多数人对WiFi的经验都涉及到连接到一个基础设施网络。在家里,您可以把WiFi接入点插入调制解调器,这样就能创建一个WiFi网络。接入点会广播一个网络名称,并在一个特定的频道上接受客户端。

为了访问互联网上的其他设备,我们需要向接入点发送WiFi帧(1)。之后,接入点将它们发送到调制解调器(2),而调制解调器继续将它们发送到您的ISP(3,4),后者会将它们发送到互联网。

1.png                                                 

典型家庭网络的拓扑结构

为了连接家庭WiFi网络上的其他设备,我们需要向接入点发送WiFi帧,而接入点会将它们转发到其他设备。

1.png

WiFi客户端都是通过接入点进行通信的,即使它们彼此都在WiFi范围内,它们也无法直接通信。

在现实中,无线信号在客户端和接入点之间不是以直线传播,而是在空间中弥漫,所以,两个客户端设备是可以看到对方传送到接入点的帧的。

既然WiFi客户端设备可以直接向对方发送WiFi帧,那么为什么还要绕道接入点呢?如果没有接入点做“中间商”的话,您当然可以拥有更多神奇的体验:“直接就用”,根本不需要任何物理设置。

实际上,有许多协议都可以做到这一点,并且每个协议都有各自的权衡。例如,隧道式直接链接设置(TDLS)协议允许已经位于同一WiFi网络上的两个设备通过协商直接连接到对方,这样的话,帧就无需通过接入点进行转发了。

此外,Wi-Fi Direct协议则允许两个不在同一网络上的设备建立一个加密的点对点Wi-Fi网络,方法是通过WPS启动一个WPA2加密的自组织网络。

对于苹果的AWDL协议来说,即使对等设备不在同一个网络上也能建立对等连接,但与Wi-Fi Direct协议不同,AWDL没有内置加密功能。此外,与TDLS和Wi-Fi Direct不同,AWDL网络还可以包含两个以上的对等体,它们也可以形成一个需要多跳的网状网络配置。

AWDL还有一个绝技:一个AWDL客户端可以同时连接到AWDL网状网络和基于AP的常规基础设施网络,只需使用一个Wi-Fi芯片组和天线即可。为了弄清楚其运行机制,我们需要深入了解Wi-Fi的基本原理。


小结

在这篇文章中,我们将为读者详细介绍近期在iOS中发现的一个零点击无线电近程漏洞,由于篇幅过大,我们将分多篇发表。更多精彩内容,敬请期待!

 

下一篇:详解iOS零点击无线电近程漏洞 (二)|NOSEC安全讯息平台 - 白帽汇安全研究院

原文地址:https://googleprojectzero.blogspot.com/2020/12/an-ios-zero-click-radio-proximity.html

最新评论

昵称
邮箱
提交评论