物联网设备固件的安全性分析(上篇)

百家 作者:绿盟科技 2018-07-31 10:27:30

引言

随着物联网设备的普及,物联网设备的安全问题也逐渐被“有心人”挖掘出来,如2017年9月,一位黑客通过分析某共享单车的固件,发掘了4种攻击方法,并控制了共享单车;2017年10月,某智能灯泡也被成功入侵,因为其固件中泄露了密钥相关的信息;又如,ReCon BRX 2018会议上,来自美国东北大学的两位研究员逆向了某公司的物联网设备的内部固件,发现了整个公司生态存在的漏洞。


研究员和黑客这些“有心人”在研究物联网设备时,为什么要获取物联网设备固件,又是如何获取物联网设备固件的呢?这三个案例中提到的漏洞,都是因为物联网设备的固件被研究员获取到,进而逆向分析后才发现的。更多的案例,可以在ReCon、BlackHat会议的官网上找到。通过分析物联网设备遭受攻击的链条可以发现,他们获取固件,把固件逆向成汇编或C程序语言后,能分析出设备的运行流程和网络行为,还能找到安全加密相关的密钥相关的信息。如果这些“有心人”没能获取到固件信息,他们也很难发现这些漏洞。从这一点看,物联网设备的安全性,在很大程度上决定于其固件的安全性。


那有没有一些方式可以防止“有心人”获取固件?想要回答这个问题,必须得知道固件在物联网设备中是怎么存储的,还要理清物联网设备固件的获取方法有哪些,才能回答如何防止获取到固件的问题。接下来,本文将围绕固件的存储方式、获取方法和防护方法来呈现物联网设备固件的安全性。


本文将被分两篇微信文章为读者呈现全部内容,上篇,将介绍“有心人”获取固件所需的存储位置信息以及获取方法。下篇,将为各位读者介绍物联网设备固件的防护方法。


存储位置

从计算机体系结构(以冯·诺依曼体系结构为例)看,固件被存储在存储器中,以方便CPU寻址、读指令、译指令等。 “有心人”只要知道物联网设备的组成部分中,哪些元器件具备存储固件的能力,就能大体知道固件在物联网设备上的存储位置了。

图 1  冯·诺依曼体系结构

仅仅知道固件在存储器中,也是不够的,还应该知道固件在存储器的哪个部分。因为存储器中的数据是根据地址来读取和写入的。 “有心人”必须知道物联网设备固件被厂家写入的地址,才算完整地获取到固件的位置信息。


既然固件被存储在存储器中,那一定可以在物联网设备的主板上找到固件的存储芯片,进而定位物联网设备的固件。一般,固件在主板上存储的方式,可以简单分成两类:集成式和分离式。分别如图 2和图 3所示。

图 2  集成式存储

图 3  分离式存储


集成式固件存储

当设备的功能比较简单,不需要运行复杂的操作系统或者集成复杂的协议栈,也不需要足够强的计算性能,一般厂商会把固件集成到他们的主控芯片中,以节约成本。暂且把这类设备称为弱设备。


弱设备和个人电脑的组成有很大的不同。一般而言,个人电脑会有非常大的硬盘(10G以上)来存储操作系统,以满足操作系统的正常运行;而几乎全部的弱设备只需要百K容量级别的固件即可正常运行。为了满足系统集成的需要,主控器厂商(如ST、NXP等)把系统正常运行所需的内存(RAM),硬盘(Flash等可重复擦写、掉电数据不丢失的存储器),CPU(计算核心)和外围接口(用于同外围设备通信)集成到一个芯片中,这个芯片由于通常用于对传感器、电机等外围设备的简单控制,又被称为微型控制单元(MCU),也就是常说的主控器。如图 4所示。

图 4  JN5169主控芯片(具备射频功能)内部组成

从内部集成的32bit RISC CPU来看,其寻址能力可以达到2^32字节,也就是4GB。其内部的固件一定会被存放在ROM中,也就是Flash或者EEPROM中,一般,设备的固件会被写入到Flash中,EEPROM用于重要系统参数或数据存放。

图 5  JN5169内存地址功能分布图

如图 5所示,在可寻址的4GB的空间内,Flash区域的地址空间为0x00080000~0x00100000(512KB)。只要“有心人”能通过某种方法,读取到这段地址空间中的数据,固件也就得到了。这个方法在下一章介绍,接下来先介绍分离式的情况。


分离式固件存储

当主控器内部的存储容量不能完全存储所需的固件或信息时,厂商一般会外接存储器到主控器上,一般,存储器会有下面3种,如图 6所示(下面三个芯片),对应来看,上面的设备可以作为读取下面的存储器的模块来使用,插入电脑,利用配套软件即可读出固件,这时候,“有心人”无需知道这三类存储器在主控器或CPU中的地址映射是怎样的,直接把芯片取下来,对应模块读出即可。

图 6  三类外挂存储器

但如果不取下这些芯片,有没有可以读出来的办法?那就通过Bootloader或者利用JTAG/SWD等调试接口,把通过控制主控器的读写存储器流程,进而读出固件内容。利用这种方式读取固件内容,需要知道这类存储器的地址在主控器中被映射到了哪段固件在存储器中的位置,寻找方法类似JN5169的固件地址,这里不再赘述。


 固件获取方法

 网络升级截获(FTP、HTTP)

固件不仅可以在本地获取。当物联网设备进入升级流程时,可以通过抓取升级过程的流量信息,进而得到物联网设备通过网络升级固件的具体途径,进而复现固件升级流程而获取固件。

例如,在某摄像头的升级流程中,物联网设备通过请求FTP服务器,进而下载到固件,如图 7所示。

图 7  某摄像头FTP升级流程

再如,在某物联网设备升级流程中,物联网设备通过HTTP协议,向云端发起GET请求,进而获取到固件,如图 8所示。

图 8  某物联网设备通过HTTP升级流程

通过抓取网络升级过程的流量进而获取固件的方法,适合在设备购买回来第一时间进行抓包,因为有的设备通过静默升级的方式来升级固件,用户是感知不到的。如果设备采取的是静默升级的方式,而此时设备刚好是最新的固件版本,设备将不会进入升级流程,此时固件是没有办法通过升级来获取的。此时,“有心人”会通过本章其他小节中介绍的方式来获取固件。


 直接读存储芯片

上一章介绍了分离式固件存储方式下,固件在物联网设备主板上所处的位置。本节介绍“有心人”是如何直接读取存储器中的数据,进而获取到固件的。


既然是直接把存储器通过焊接的方式取下来,必然需要用到焊接工具,如图 9所示。攻击者将存储器焊接下来之后,将用到图 11所示的编程器把固件从图 10所示存储器中读取到。其他两种存储器的读取方式,和这个流程类似,此处不再赘述。

图 9  拆焊台

图 10  某路由器存储器

图 11  NandFlash芯片编程器

“有心人”除了有这个编程器以外,还会从卖家得到一个配套软件,运行在PC上,作为上位机读取NandFlash中的内容,如。图 12所示。利用该软件和编程器,将存储芯片和PC建立连接后,直接读出即可。

图 12  NandFlash读取所用上位机


通过串口等通信总线读取

上节提到的方式简单粗暴,“有心者”获取固件的方式中,还有一种比较“温柔”的方式,那就是通过主板上暴露的UART接口,在PC与固化在主控器中的Bootloader程序之间建立通信,进而通过控制主控器读取固件中指令的流程,把固件读取出来。此处以STM32单片机为例,介绍如何利用主控器内部的Bootloader进而得到主控器内部的Flash区域的代码。

图 13  PC通过UART通信总线与目标设备通信

关于Bootloader,ST公司对其STM32系列产品有如下描述:“自举程序存储在 STM32 器件的内部自举 ROM 存储器(系统存储器)中。在生产期间由 ST编程。其主要任务是通过一种可用的串行外设(USART、CAN、USB、I2C 等)将应用程序下 载到内部 Flash 中。每种串行接口都定义了相应的通信协议,其中包含兼容的命令集和序列。” 


从官方介绍来看,这段Bootloader的主要作用是方便芯片使用者(嵌入式软件开发工程师)下载固件程序到主控器的Flash区域中。事实上,除了这个功能外,Bootloader还具备读取固件的能力。这要从Bootloader的整个运行流程谈起。

图 14  Bootloader启动流程

从启动流程上看,如果Bootloader被激活运行(一般是通过硬件上的引脚状态设置),主控芯片一定会停留在一个等待命令的状态,这个状态允许另外一台主机(如通过串口总线连接主控器的PC)通过串口通信发送命令,以下载固件到存储器或读取存储器中的内容。如果主机传入RD命令,将会进入读取存储器内部数据的流程。


当从机从主机端接收到0x11+0xEE时,接下来,主机会给从机传输读取的数据所在地址以及读取的容量大小,从机就会把数据发送到主机端,此时,只要主机端把接收到的数据以二进制或16进制的形式存储成文件,即可得到固件。读取数据的流程如图 15所示。

图 15  Bootloader RD命令的流程-主机端(左)/主控器(右)

利用Bootloader读取其他MCU的方法类似,参考官方文档对其Bootloader程序的描述即可。如果官方的芯片手册中没有提供通过外部通信接口读取固件的通信流程和时序,就意味着两种情况:其一,生产该芯片的公司不会把通过Bootloader读取固件的方法开放出来;其二,生产该芯片的公司没有把通过外部通信接口读取固件的电路设计到芯片中。无论是哪种情况,厂商已经把Bootloader获取固件的方法封闭或禁止了。如瑞萨电子(MCU厂商)就是这样做的。如果官方提供的Bootloader程序中没有读取固件的功能,但是芯片手册中提供了读取流程和通信时序,就可以参考芯片的官方手册写一个第三方Bootloader来代替物联网设备中的Bootloader,这样开发成本会大一些,不如选择利用硬件调试接口来读取存储在设备固件中的内容。


通过调试接口读取

有些产品的主板上,会暴露硬件开发调试时所用的接口,如JTAG/SWD接口。一般,如果只是利用串口,在开发调试阶段是没办法设置程序断点的,所以厂商实现了JTAG/SWD硬件模块,以特定的协议,通过一个硬件调试器作为通信协议适配器,方便开发者在PC上动态调试正在运行在芯片中的代码。利用JTAG/SWD的接口,使PC与主控器建立连接和适配后,相当于控制整个芯片或者设备。


以SWD接口为例。利用SWD接口和相配套的硬件调试器,将PC和物联网设备建立连接的接线方法,如图 16所示。

图 16  SWD接线方法

当PC与主控芯片建立连接后,需要参考SWD接口的通信协议规范,把存储在Flash中的数据读取出来,才能获取固件。与通过Bootloader读取固件的方式不同,生产硬件调试器的厂商会提供一个配套软件作为主机端程序,如J-Link驱动程序等,使PC运行J-Link驱动中的程序后,可以向主控器的存储器中写入数据、读取数据,也可以运行指令、设置断点等,实现硬件调试的效果。

图 17  J-Link驱动配套软件

以J-Link驱动程序为例,J-Link驱动程序与J-Link硬件调试器配套。PC安装完J-Link的驱动程序之后,会带有如图 17所示的软件。运行J-Link Commander和J-Flash ARM都可以建立PC与芯片之间的连接并读取出固件。J-Link GDB Server via SWD/JTAG可以建立一个GDB调试服务,使用平常调试用的gdb即可动态调试主控芯片。


小结

以上,介绍了“有心人”获取固件所需的输入信息以及获取方法。究其(固件提取)本质,还是在获取Flash、RAM的访问权限,进而读取映射到内存地址中的内容。在获取方法的介绍过程中,有意对方法分类,分类的依据是该方法需要控制设备的程度。如:方法1利用升级的方法,只是利用了设备的工作模式,而没有去控制设备,即可获取固件;方法2直接读取存储器的方法,绕过了控制设备控制器(或处理器),直接控制设备的Flash芯片,直接把芯片中的整片内容读取到;方法3则需要控制MCU(或处理器)的Bootloader中读取Flash的流程,进而把数据通过通信总线输出到主机端(如PC);方法4则控制了整个MCU(或处理器),就是通常说的进入了上帝模式。

物联网设备的固件安全性,本篇从攻击的角度,呈现上述内容,下篇将从防护角度,为各位读者呈现:如何防止固件被“有心人”获取,从而大大增加物联网设备的安全性。


本文所有图片均来源于网络和官方手册截图。本文所有内容,避免不了有所疏忽,如果您认为本文所阐述的内容是错误的或者对本文的观点持有不同意见,非常欢迎您及时指出并随时交流。




请点击屏幕右上方“…”

关注绿盟科技公众号
NSFOCUS-weixin

↑↑↑长按二维码,下载绿盟云APP


关注公众号:拾黑(shiheibook)了解更多

[广告]赞助链接:

四季很好,只要有你,文娱排行榜:https://www.yaopaiming.com/
让资讯触达的更精准有趣:https://www.0xu.cn/

公众号 关注网络尖刀微信公众号
随时掌握互联网精彩
赞助链接