近十年,随着传感器技术、无线通信技术的迅速发展,越来越多的物联网产品出现在我们的视野中,Gartner预测,到2020年,物联网设备的装机量将超过200亿,但很多物联网设备受到成本、研发人员安全素质等因素的限制,存在大量的安全问题。例如2016年底的Mirai事件,就是因为弱口令和未修复的设备漏洞引起的。物联网终端的安全,也越来越受到人们的关注。
2017年10月,物联网安全研究人员渗透进了某智能灯泡,获取到了Mesh网络内传输的WiFi信息(包括WiFi密码)。尽管在该案例中WiFi密码被加密,但是研究人员依然通过获取设备的底层固件,得到了加密算法和密钥信息,最终得到了明文的WiFi密码。固件提取进而分析固件是攻击者常见的渗透手段,反之如果厂商想要生产出高安全级别的智能灯泡,第一步就是要防止固件内容被窃取。
接下来,我们对这次案例做个简单的分析,然后进一步分析固件提取原理和过程,最后总结在现有的技术背景下获取固件的方法和相应的防护方法。为了描述方便,我们把这种获取固件的技术称为固件提取。
案例回放
(图片来源于FreeBuf)
文章中提到的攻击,可以分3步:
1.利用单片机和支持IEEE 802.15.4无线通信的模块来抓取6LoWPAN流量中的数据,提取出WiFi信息(此时加密的)。
2.通过提取固件、分析固件,分析出其采用的是AES加密算法,并提取出加密密钥和初始向量等信息。
3.根据2中获取的信息来解密得到WiFi密码。
这是一个典型的针对家庭局域网络内的嗅探攻击。今后的物联网设备将有一大部分是作为Mesh网络节点存在,只不过网关可能是手机、路由器、笔记本电脑等一切具备蓝牙、ZigBee、WiFi等无线联网能力的设备。基于现有的网络来看今后的物联网,设备如果想要具有联网能力,则必须利用至少一条有线或无线的通道连接到互联网。如果是通过WiFi连接,必要的信息就是WiFi的SSID和密码。
案例中,攻击者通过分析固件得到了解密WiFi密码所需的信息——加密密钥和AES初始向量。那为什么研究人员可以获取到固件呢?下面我们将分析固件提取的原理,并且分析在现有的技术背景下,提取低性能的物联网节点上的智能设备的固件方法。
固件提取的原理
我们已经理清楚了攻击的方法,本次就针对其中重要一环——固件提取,谈一谈固件提取的原理,进而总结现有的固件提取方法。
以STM32F103系列单片机为例。该单片机基于ARM Cortex M3内核,片内带有64KB的Flash和20KB的SRAM。单片机读取程序到SRAM再进行译码。目前已知的有两个地方会存储需要运行的程序:
1.单片机内的Flash/ROM。
2.单片机外挂的Flash/ROM。
对于存储器来说,读和写的操作是最基本的,即:必然存在一种方式,可以把存储器中的数据读取出来。如果读取的数据是单片机需要翻译的机器码,那么我们就把读取的过程叫提取,把要读取的数据称为固件。
stm32f103c8t6单片机的片内Flash的地址是0x08000000-0x0801ffff(如上图所示),总共64KB。如果要提取出固件,有必要了解代码是如何烧写进芯片内的Flash区域里面的。
在开发过程中,会有如下过程:
1.搭建好编译环境,编写程序代码(一般采用高级程序设计语言,如C语言),编译、生成可执行文件。
2.搭建好烧写环境,把可执行文件传到单片机芯片中,使单片机上电可以运行。
编译环境就是用把单片机C语言程序编译成汇编、机器码等,生成16进制hex文件或者二进制bin文件,一个编译器即可。烧写环境就是把机器码下载到上图的Flash区域的过程中所需的工具,包含J-link、U-link、ST-LINK(stm32单片机专用)等硬件工具和STVP、mcuisp等软件(使用一套软硬件即可)
请注意,烧写、下载、上传、提取这四个词,说白了,就是对Flash区域读写的过程。目前发现两种读取固件的方式,第一种是依托于生产厂商固化在芯片内的bootloader,把Flash中的固件读取出来,第二种是通过调试接口把固件读出来。第一种需要bootloader支持,而且一般是支持的。第二种是依靠硬件调试工具直接读取,在前面的案例中,研究人员通过PCB上保留的JTAG调试接口,把固件读取了出来。
篇幅所限,读取过程中的交互细节不多介绍,直接介绍两类固件提取的工具和方法,一类是以stm32单片机为例的单片机固件提取的工具和方法,一类是外挂Flash形式的Flash固件提取的工具和方法。
单片机片内Flash的固件提取的工具和方法
单片机固件提取方式有两类,一类是通过bootloader读取,一类是通过调试接口读取。
- 利用bootloader提取。
通过串口,把芯片和电脑相连,运行mcuisp软件,点击读Flash即可。
mcuisp软件通常被用来通过串口通信下载固件到单片机。串口通信也是通信技术的一种,目的是实现芯片A到芯片B的数据传输,是芯片之间经常用到的通信方式。例如:如果我的目的是把程序代码“abcd”传输到芯片A中,但是,我仅仅通过电脑与没有bootloader的单片机进行串口通信,“abcd”是没办法直接储存到Flash区域的,必须在单片机内部写好一段代码,在“abcd”已经通过串行接口,一个一个的到达单片机内部的缓冲器时,把 “abcd”一个一个的转存到Flash区域。这样就实现一种电脑直接写入“abcd”到Flash的假象,达到用户无感知或是透明传输的效果。提取固件的过程相反与上述过程相反,只需要利用bootloader把Flash的内容通过串口通信发送给电脑即可。
- 利用硬件调试接口提取。
在开发单片机程序时,会用到硬件调试工具,实现单步运行来查看程序实时运行的效果。一般可以通过下面两类调试接口,把Flash中的数据读取出来。
(1)SWD接口,利用硬件:J-LINK OB或者J-LINK或者ST-LINK;利用软件:J-LINK驱动程序自带的J-FLASH或者ST官网提供的STVP。
(2)JTAG接口,利用硬件:J-LINK;利用软件:J-LINK驱动自带的J-FLASH。
如果找不到串行接口,可以用这种方式,当然,前提是产品电路板上可以引出这两类接口之一,否则只能取下芯片了。
单片机片外Flash的固件提取工具和方法
作为一个存储器,上电之后不可能自己就把数据显示给我们,就好像U盘买回来,得插电脑上,加载完驱动才能读取到里面的数据。对于片外Flash,需要把Flash芯片从产品的电路板中取下来,再放到另外一个带有MCU的电路板上来读取数据。万能的淘宝提供了编程器,方便了对众多Flash芯片的内部数据的提取。
这种方式有两个缺点:一是比较暴力,需要把Flash芯片从电路板上取下来,再把Flash芯片放到编程器上面,利用配套的PC端软件,把固件读取出来。二是Flash芯片型号需要得到编程器的支持。那问题来了,如果这个编程器不支持我的Flash的型号呢?那就自己写个单片机程序把程序读出来吧。一般,在大学本科修读电子信息工程、通信工程或自动化专业的,有独立硬件项目开发经验的同学,都可以独立实现。
防护措施
介绍了这么多提取固件的工具和方法,那现在有哪些方法能有效防止产品固件被提取出来呢?
针对单片机固件提取的防护:我们可以通过编程的方式,把内部Flash区域设置为读保护状态,这样只要不对MCU进行解封,利用显微镜对内部Flash的电平状态进行破坏,是很难篡改固件的,至于读取固件,基本上不可能。例如,我们对stm32单片机的RDP寄存器进行设置,使内存保护等级提升至level 2,或者把重要的程序和数据利用PCROP功能保护起来,防止读取。
对外挂的Flash内的固件,目前,就本人所知,只要能取下来,获得型号,就可以得到固件。那问题就变成了:如何不让攻击者把Flash安全地取下来?我建议硬件设计工程师把PCB上的Flash芯片,依靠电路设计保护起来。例如:设计Flash芯片在线检测电路,一旦Flash芯片的引脚出现断线,则立刻发动强电压攻击,将Flash芯片破坏,防止攻击者读取出Flash芯片中的固件。
总结
我们通过分析固件提取的原理,介绍固件提取可用的方法和工具以及相应的防护措施,希望可以使更多的电子工程师、嵌入式软件工程师重视智能设备固件的保护。同时,我们希望这篇文章可以给物联网安全从业人员带来一些物联网设备的防护建议。希望在智能设备开发工程师和安全测评工程师的共同努力下,我们身边的智能设备变得越来越安全。