使用恶意ZigBee灯泡渗透网络

2020-08-08 15:33:57

每个人都熟悉物联网(物联网)的概念,但有多少人听说过智能灯泡呢?只需使用移动应用程序或数字家庭助手,您就可以控制家里的灯光,甚至可以校准每个灯泡的颜色。智能灯泡的管理是通过WiFi甚至ZigBee(一种低带宽无线电协议)来完成的。

几年前,一组学术研究人员展示了他们如何接管和控制智能灯泡,以及这反过来如何让他们创造出可以蔓延到整个现代城市的连锁反应。他们的研究提出了一个有趣的问题:除了引发停电(可能还会引发几次癫痫发作)外,这些灯泡是否会对我们的网络安全构成严重威胁?攻击者能否以某种方式弥合物理物联网网络(灯泡)与更具吸引力的目标(如我们家庭、办公室甚至智能城市中的计算机网络)之间的差距?

继续之前的研究,我们直接进入核心:智能集线器,它充当IP网络和ZigBee网络之间的桥梁。通过伪装成合法的ZigBee灯泡,我们能够利用我们在网桥中发现的漏洞,使我们能够使用远程空中ZigBee漏洞渗透到利润丰厚的IP网络。

这项研究是在特拉维夫大学Check Point信息安全研究所(CPIIS)的帮助下完成的。

在我们完成了前面的研究之后(比如Cheese:How I Ransomwared Your DSLR Camera),我们决定扩展我们的调试器(Scout)来支持其他架构,比如MIPS。要做到这一点,最好的方法是开始研究MIPS,我在Twitter上询问了一个好的MIPS目标的建议,以进行漏洞研究。

就像大多数情况一样,人们的反应是一些有希望的线索,其中最有希望的是我的一位老同事EYAL RONEN(@eyalr0),他现在CPIIS(小世界,不是吗?)担任研究职位。埃亚尔·罗宁建议我继续他对智能灯泡的研究(参见下一节的“前期工作”)。在他们最初的研究中,他的团队只能自己控制灯泡。他认为有可能利用ZigBee网络中的这一地位,对连接ZigBee网络和IP网络的网桥进行攻击。本质上,这种新的攻击载体使攻击者能够使用空中攻击从ZigBee网络渗透到IP网络。

在IoT Go Nuclear:Creating a ZigBee Chain Reaction中,由EYAL RONEN(@eyalr0)、Colin O‘Flynn(@colinoflynn)和Adi Shamir领导的研究团队分析了ZigBee智能灯泡的安全方面。更具体地说,他们将重点放在飞利浦色桥和灯泡上,展示了一系列的功绩:

攻击者可以远程从给定的zigbee网络“窃取”一个灯泡,并强迫它加入他们的网络(使用无人机战争演示--从400m高空飞行):https://www.youtube.com/watch?v=Ed1OjAuRARU

由于实现缺陷,即使是普通的灯泡也可用于部署此类攻击,并从相邻的ZigBee网络“窃取”灯泡。

与目标灯泡共享同一ZigBee网络的攻击者可以向该灯泡发送恶意固件更新,从而完全控制该灯泡。

通过将这3种已演示的攻击结合在一起,研究人员认为,通过控制智能城市中选定的灯泡子集,它们可能会引发类似核子反应的连锁反应,最终可能控制城市中的所有灯泡。

由于攻击的性质,供应商只能阻止第二次攻击,因此我们有能力:

从一个给定的近距离(400米)的ZigBee网络中“偷”一个灯泡。

更新那个灯泡的固件,然后用它来发动下一阶段的攻击。

在得到他们最初研究的详细解释,并配备了埃亚尔·R从他们实验室抢救出来的飞利浦色桥后,我们准备开始这项有前途的新研究。

根据维基百科的说法,“ZigBee是一种基于IEEE802.15.4的规范,用于创建…的一套高级通信协议。低功率、低数据速率和近距离无线自组织网络。“。不要与IEEE802.15.4(WiFi)混淆,根据开放系统互连模型,IEEE802.15.4是基于无线的网络协议的技术标准,它充当ZigBee网络堆栈的1-2层。

仅为了了解这种低数据速率协议,IEEE 802.15.4的底层MAC层中帧的最大传输单位(MTU)为127字节。这意味着除非使用分段,否则ZigBee网络堆栈的消息大小非常有限。希望这个限制不会太多地限制我们在ZigBee实现中发现漏洞,并在以后利用这些漏洞。

在狭窄的无线网络层之上,ZigBee定义了完整的网络层堆栈,如取自ZigBee规范(较旧版本)的下图所示:

简而言之,我们可以将网络堆栈大致分为4层(按升序排列):

应用层(ZDP/ZCL/等)-逻辑应用层,取决于传入的消息(多层同时存在)。

对于熟悉SNMP协议的人来说,ZCL看起来像是同一逻辑接口的不同编码。ZCL层允许设备查询(READ_ATTRIBUTE)和设置(WRITE_ATTRIBUTE)配置值(群集)的集合,这最终允许操作员(桥接器)控制灯泡。例如,颜色控制群集的属性包括:

此示例还表明,这些不是普通的白色/黄色灯泡。这些智能灯泡支持多种颜色,可以使用(RGB)调色板进行控制。

我们这项研究的目标是飞利浦色调系列产品,更具体地说,是飞利浦色调桥。附注:色调系列产品起源于飞利浦的飞利浦照明部门,现在是第三家名为Signify的公司的品牌。

虽然“智能”照明解决方案在以色列还不那么受欢迎,但我们发现在许多其他国家情况并非如此。例如,2018年的这篇文章称,飞利浦色调占据了英国智能照明市场31%的份额,有超过43万个家庭使用。事实上,当我们向我们公司的一些副总裁介绍我们的研究结果时,他们告诉我们,他们房子里所有的灯都是飞利浦色调品牌的。

下图摘自原始研究论文,显示了使用此产品的家庭或办公室的网络架构:

ZLL是ZigBee Light Link的首字母缩写,ZigBee Light Link是ZigBee网络堆栈的定制层,专注于照明设备:灯泡和控制灯泡的网桥。

一方面,我们有ZigBee设备:灯泡、开关和电桥。另一方面,我们在“常规”计算机网络中有IP设备:我们的手机、路由器,还有网桥。根据他的名字推断,网桥是两个网络中唯一存在的设备,它的作用是将我们从移动应用程序发送的命令转换为ZigBee无线电消息,然后发送到灯泡。

我们已经知道桥使用的是MIPS CPU(这就是我们最初选择它的原因),但事实证明它的架构更加复杂。在图3中,我们显示了从塑料外壳中提取后的桥接板(2.0型号):

左边用红色标记,是实现ZigBee堆栈较低层的Atmel CPU(ATSAMR21E18E)。

从现在开始,我们将Atmel CPU称为调制解调器。这主要是因为主CPU卸载了仅在该处理器上执行的低级ZigBee网络任务的处理。这意味着物理层和NWK层都由调制解调器处理,而调制解调器可能会向主CPU查询所需的配置值。

令我们惊讶的是,主CPU运行的是Linux内核,而不是实时操作系统。当我们必须提取固件并调试负责网桥核心逻辑的主进程时,这被证明是非常有用的。

Colin O‘Flynn(@colinoflynn)在他的网站上介绍了如何连接到暴露的串口并获得主板上的root权限。对于任何与嵌入式Linux设备打交道,特别是U-Boot引导加载程序的人来说,这是一本很棒的指南。不幸的是,我没有必要的设备连接到串行接口,这是我在多次未能重现科林的结果后发现的。幸运的是,我咨询了我的小弟弟,他帮我解决了问题,并告诉我需要订购哪些串行电缆。因此,我们开始对我从EYAL R那里收到的旧固件版本(从2016年开始)进行反向工程,当时我正在等待电报的到达。

主CPU中的核心进程是ipbridge进程。基本侦察显示,这是ELF目标的典型案例:

这是我们在处理运行Linux的目标时经常看到的一种混合状态。操作系统默认启用一些安全功能,通常供应商不会主动启用其他功能,如PIE(独立于位置的可执行文件)甚至堆栈金丝雀。从我们作为攻击者的角度来看,攻击并不容易,因为有一些ASLR(地址空间布局随机化),但它仍然是可能的,因为我们可以在攻击中使用一些固定的已知内存地址。

在开始对该过程进行反向工程之前,我们注意到反汇编程序很难区分MIPS和Mips16代码段(类似于ARM固件中的ARM和Thumb)。这是测试竖起大拇指(最初只在Intel和ARM二进制文件上测试)是否也能在我们的Mips二进制文件中产生改进的分析的好时机。对我们来说幸运的是,它工作得很好:最初我们有2525个函数,执行之后我们有了一个更干净的二进制文件,其中有3478个标记的函数。现在,我们开始逆向工程我们的二进制文件,而不需要手动改进IDA Pro的分析。

在我们开始逆向工程阶段后,我们立即看到了一些奇怪的事情。出于某种原因,我们似乎希望我们的消息以文本形式到达?!

在图4中,我们可以看到我们希望在传入消息中找到的字符串列表。每个字符串路由我们的消息到一个特定的处理程序函数,比如我们命名为ei_zcl_main_handler的函数。在这一点上,我们再次检查了ZigBee的规格,因为它没有任何意义。协议应该是二进制的,而且带宽非常低,为什么我们的程序认为它应该接收长字符串呢?

在再次阅读了埃亚尔·R和科林的结论后,它突然变得清晰起来。调制解调器还有一个我们最初忽略的额外作用:它将二进制消息转换为文本表示形式,然后通过USB转串行接口发送它们。这样,主CPU从在操作系统中映射为文件的串行设备读取易于处理的文本消息。

Colin发现了灯泡使用Atmel BitCloud SDK的证据,该SDK现在是封闭源代码的,必须从Atmel购买。因此,假设相同的软件堆栈也用作网桥中调制解调器CPU的“解码器”层是有意义的:

这样,主CPU只需要熟悉ZigBee堆栈的逻辑方面,而不需要实现复杂的解码和解析功能,这些功能已经包含在随Atmel调制解调器提供的堆栈中。

从安全的角度来看,这种设计选择有其利弊。就我们而言,它有巨大的影响。我们只有ipbridge进程的固件,也可以使用我们编译并放置在桥的文件系统上的远程gdbserver进行调试。调制解调器的固件是加密的,要重新创建原始研究中的步骤以提取此密钥(使用功率分析攻击)并解密调制解调器的固件并非易事。

这意味着我们只能将调制解调器视为执行大量解析的黑盒,甚至可能包含几个状态机。我们从GitHub上发现的部分代码版本(也就是几年前的版本)中得到了一些提示,但实际上它只是一个黑匣子,如果他们要求我们发送格式错误的消息,它就可以阻止我们的一些攻击尝试。

这项研究没有什么是容易的,所以,我们只是在我们的清单上增加了这个新的障碍,并继续下去。

现在我们了解了调制解调器向串行设备发送文本消息的原因,我们跟踪了不同线程之间的消息流,并开始在每个不同的处理程序中查找漏洞。我们的工作重点放在ZCL处理程序上,因为它支持对各种数据类型属性的读/写操作:

正如您可能了解的那样,在嵌入式设备中处理可变长度字段肯定会导致漏洞。图5显示了处理此情况的汇编代码:

注意:请记住,MIPS体系结构使用延迟槽,因此在调用malloc()时,值0x2B作为指令中延迟槽内的参数传递:li=$a0,0x2B。对于任何第一次阅读MIPS汇编的人来说,这可能会让人有点困惑。

我们发现了什么?攻击者可以对READ_ATTRIBUTE消息发送恶意响应,该消息包含大于固定大小43字节(0x2B)的格式错误的字节数组。这会触发基于堆的受控缓冲区溢出,没有任何字节限制。

由于ZCL是ZigBee堆栈中相对较高的层,我们只能发送最多70字节的数组。否则,我们的消息将大于网络限制。

状态机检查可能会强制我们仅使用正确的请求数据类型进行响应。

这并不是最容易利用的漏洞,但它仍然是一个严重的漏洞。

在一个很好的时机,我们的串行电缆终于到达,我们立即开始检查是否确实发现了漏洞。我们编译了一个gdbserver并将其放在桥的文件系统上,现在遇到了一个新的障碍:我们没有用来发送攻击的发射器。在与埃亚尔·R再次商议后,我们购买了灯泡CPU的评估板,与他的团队在他们的研究中所做的完全一样。

与此同时,我们发现了一种黑客攻击,它允许我们验证该漏洞的存在,即使不需要通过空中传输无线电消息(希望调制解调器稍后不会阻止我们)。Ipbridge进程支持调试测试模式,该模式通过连接到进程使用调试线程侦听的两个命名管道来激活:/tmp/ipbridge geio_in和/tmp/ipbridge geio_out。虽然这些调试功能没有真正的帮助,但我们修补了二进制文件,以便通过这些管道到达的消息被添加到消息队列中,就好像它们是从调制解调器本身到达的一样。

使用这个小的二进制补丁,我们能够创建我们自己的进程,该进程连接到命名管道并发送(文本)消息,目的是攻击易受攻击的代码函数。经过反复试验,并使用我们的调试器,我们能够触发该漏洞并证明它的存在。唯一的警告是调制解调器仍然可以阻止它,这需要我们通过无线电传输攻击。

在等待我们的发射器时,我们全套的飞利浦色调入门套件送来了一个全新的2.1型号桥架和3个灯泡。这看起来是从网桥提取新固件的合适时机,同时将2.0网桥更新为最新固件。毕竟,到目前为止,我们从2016年开始从事固件工作,在此期间,情况可能发生了变化。

关于新固件,我们首先注意到的是它的大小。由于某些原因,ipbridge ELF文件从1221KB增加到3227KB。在IDA Pro中打开它向我们展示了主要的不同之处:二进制文件是(意外的?)。附带调试符号。这是一个非常好的消息,可以真正帮助我们进行逆向工程的尝试。图6显示了其中一些符号:

使用这个新发现,我们了解到最初的反向工程是相对准确的,易受攻击函数的名称原来是:Smartlink_utils_ReadAttributeValue。

在分析新固件版本中易受攻击的功能时,我们有了一个令人不快的惊喜。支持的数据类型列表已更新,现在供应商支持字符串(0x42)而不是字节数组(0x48)。虽然字符串的长度仍然是可变的,但分配现在已更改为更适合以NULL结尾的字符串:

不再使用固定的堆缓冲区,并且对支持的数据类型的更改刚刚关闭了我们的漏洞。是时候去找新的了。

我们把ZCL模块放在一边,最终找到了到ZDP模块的方法,更具体地说,找到了进入LQI(链路质量指示器)管理响应的处理程序。这些消息是负责邻居发现的模块的一部分。网桥定期向灯泡查询其在ZigBee网络中的已知邻居。虽然名称暗示消息侧重于无线电传输的质量,但消息结构实际上侧重于每个邻居的全套网络地址。

8字节扩展地址:全球唯一的网络地址(类似于以太网MAC地址)。

2字节-网络地址:在当前ZigBee网络中本地唯一的短网络地址。

2字节-PAN ID:个人区域网络标识符,本地ZigBee网络的标识符。

由于双方需要相互告知可变数量的邻居,其可以在IPBridge全局邻居阵列中包括最多0x41个受支持的记录,因此这些消息包括分段格式。在每个响应中,灯泡告诉网桥它当前正在用可能的S个记录中的L个记录(从偏移量X到偏移量X+L-1)进行应答。

您可能还记得,ZigBee堆栈中的消息大小相当小,因此在每条消息中使用如此多的索引,并分别发送多条16字节的记录,确实限制了每条消息中可以包含的记录数量。因此,开发人员将传入记录存储在堆栈中的数组中,最多可容纳6条记录。但是,没有适当的检查来确保传入的长度字段确实足够小,从而导致潜在的基于堆栈的缓冲区溢出。

您可能想知道我们计划如何传输如此“庞大”的消息并使缓冲区溢出。由于无线电对消息大小的物理限制,我们唯一的希望是找到调制解调器中的漏洞,然后利用这种基于堆栈的溢出从调制解调器跳到主CPU。这意味着即使我们刚刚发现了一个漏洞,也只能在我们甚至没有固件的额外CPU中使用一个额外的漏洞来利用它。这不是一个很好的计划,但在没有其他…的情况下。

在开始这样大胆的行动之前,我们再次使用我们的黑客注入数据包,并试图触发基于堆栈的可控缓冲区溢出,以检查此新漏洞的可利用性。不幸的是,堆栈上的返回地址正好位于溢出时我们无法完全控制的偏移量中。我们的溢出是通过解析传入字段并将它们放在本地结构中发生的。原来,我们只能用值0x00000004溢出返回地址。

结论:不可开发。至少这省去了我们尝试和寻找漏洞的需要。

.