用故障注入和二进制分析对BootLoader实施攻击

一颗小胡椒2021-10-06 05:19:11

双电压毛刺的故障攻击,侧信道史上首次!

背景介绍

Bootloader是一段在嵌入式操作系统内核运行之前,用于初始化硬件设备、建立内存空间映射图,从而将系统的软硬件环境带到一个合适状态,以便为最终调用操作系统内核准备好正确的环境的程序段,可以理解成BIOS,因此Bootloader对于嵌入式系统的安全运行起到至关重要的作用。

2020年12月,来自伯明翰大学的Jan、David、Flavio等人在顶级学术期刊TCHES上发表了一篇论文,该论文所做的事情就是通过硬件及软件手段绕过Bootloader的保护机制,从而读取微控制器内敏感的固件信息,避免与复杂的密码算法打交道,其中硬件手段部分完成了侧信道史上首次双电压毛刺的故障攻击。

这篇论文的结构如下:论文首先介绍了实验配置,然后依次对三家厂商的四种型号的微控制器进行了分析与实验,最后总结了在实验过程中发现的不安全的bootloader设计。

实验配置

论文的实验配置如图1所示,μC是目标微控制器,GIAnT用于生成时钟毛刺,Raspberry Pi用于给微控制器的bootloader发送指令,以及给GIAnT配置电压毛刺参数。右图为毛刺信号示意图,其中VF为毛刺电压,T为毛刺偏移,W为毛刺宽度。

图1 实验配置图,左图为实验装置,右图为毛刺信号,其中VF为毛刺电压,T为毛刺偏移,W为毛刺宽度。

实验过程

接下来论文依次对三家厂商的四种型号的微控制器的bootloader进行了分析与实验。

NXP LPC1xxx bootloader

恩智浦的LPC1系列bootloader根据CRP防护等级的不同存在不同级别的防护。其中论文作者通过反汇编bootloader的二进制代码并分析后发现,LPC1系列芯片的bootloader在CRP1防护等级下存在软件漏洞,在向内存写入数据时不检查写入地址是否在栈内,导致攻击者可以通过栈溢出的方式调用在CRP1防护下本应被禁用的”Read Memory”指令,从而绕过CRP1防护读取RAM中的数据。

图2是栈溢出的ROP链。其中从0x10001f54地址开始,栈内11个字的数据因为栈溢出攻击而被覆写,0x10001f54为”Write memory” 指令的返回地址,被修改成了0x1fff0cfb,刚好就是”Read memory” 指令中检查CRP防护级别后的第一条语句。

图2 ROP链,0x10001f54为“Write memory”返回地址,0x1fff0cfa为“Read memory”指令里检查CRP防护级别后的第一条语句,蓝色的FC020000为“Read memory”指令读取的地址,绿色的0x1fff0e80为执行完一个pop语句后程序回归正常运行状态。

STM8 bootloader

本节论文分析了STM8L和STM8A两个型号芯片的bootloader,图3是将bootloader二进制代码反汇编后得到的程序流图。以STM8L芯片为例,为了使程序进入_SERIAL_BL状态,即串行调试状态,需要注入两个电压毛刺,第一个毛刺跳过chk_empty或者chk_bl函数,即检查芯片是否为空或者检查“Bootloader Enable”的值;第二个毛刺跳过chk_crp,即检查芯片是否有crp防护。

图3 STM8L和STM8A bootloader程序流图,第一个电压毛刺使程序从chk_empty或者chk_bl状态进入chk_crp状态,第二个电压毛刺使程序从chk_crp状态进入_SERIAL_BL状态。

直接进行电压毛刺的故障攻击是困难的,因为在两个电压毛刺都成功注入前,芯片不会有任何反应,这导致我们无法根据芯片的反应来调整电压毛刺的参数,使得毛刺参数的搜索空间变得非常庞大。为了减小毛刺参数的搜索空间,提高毛刺的注入效率,论文将影响程序执行的关键代码段(在本小节就是指chk_empty、chk_bl和chk_crp)读入到用户程序中,然后对这些代码段单独进行毛刺注入的测试,极大地减少了电压毛刺注入的参数选择范围,提高了故障攻击调参的速度,最终实现了双电压毛刺的故障攻击。

图4 双电压毛刺故障攻击,第一个毛刺位置为检查芯片是否为空或者BL值,第二个毛刺位置为检查CRP值。

Renesas 78K0 bootloader

本节对瑞萨的78K0芯片的bootloader进行了分析,不同于STM系列芯片,芯片启动后会立刻检查防护情况,除非防护被无效否则不会继续运行。78K0芯片在启用CRP防护机制后,只允许特定安全的指令可以运行,即verify和checksum。本节通过电压毛刺修改两条指令执行的最小字节数,从256字节减少至4字节,从而破解出了内存信息。

同样为了减少电压毛刺的参数组合,本节使用了symbolic execution(符号执行)的方法,将特定指令的输入参数分成了若干等价类,从而提高了注入电压毛刺的效率。

如图5所示,将执行路径相同的输入归类为一个等价类,可以极大地提高电压毛刺偏移选择的速度。

图5 get_block_no模块输入参数等价类示意,图中两条路线对应等价类0x1004c和0x5ff。

如图6所示,论文将checksum函数的输入分成了9个等价类,由于执行路径不同,9个等价类需要设置不同的毛刺偏移。由此,大大减小了电压毛刺的参数的搜索空间。

图6 checksum函数第一个输入参数的9个等价类。

论文结论

攻击的目的是为了防御,本文攻击的设备都是商用产品,因此论文在结尾根据实验过程中的发现,提出了10条在设计微控制器时应该加以防护的漏洞,如下所示:

①在受保护状态下的部分RAM写权限:有多级保护机制的芯片往往允许对芯片内存的有限debug。没有MMU的芯片应该保证bootloader的内存空间与用户可以存取的内存空间是分开的。

②内存或寄存器的部分泄露:在CRP防护被启用时,有些芯片仍然提供对内存或者寄存器的读取权限。利用这一漏洞,Obermaier等人引入了“cold boot stepping”,基于SRAM快照重建了程序的控制流。此外,通过单步加载指令和修改CPU寄存器,Brosch恢复出了蓝牙芯片的固件信息。

③部分flash覆写:有一个sector的写权限本质上给予了攻击者对整个芯片的读权限。许多系统可以通过覆写一个flash sector,使其输出整个芯片内存而被攻破。

④不完全的或非原子的芯片擦除:许多芯片上CRP可以通过整张芯片的擦除而被无效。但是,一些情况下芯片擦除不会完全清除芯片的内部状态,导致攻击者可以恢复存储在未擦除空间的密码算法密钥。为了避免这一情况,芯片擦除过程应该是不可中断的和原子的,也就是说无效CRP的代码应该在擦除程序的最后执行。

⑤非固定时间代码:在受密码保护的bootloader上的时间泄露,例如Renesas M16C或TI MSP430,允许攻击者逐字节的恢复密码并且获得整片flash内存的读写权限。

⑥默认无防护:如果只有特定的值才启用读保护,那么相比只有特定的值才无效读保护而言,要更容易被攻击,例如LPC1343。

⑦对读保护没有冗余检查:在没有针对故障注入的硬件防护的芯片上,跳过一个检查的成功率往往是很高的,但是如果有冗余检查,就会显著地降低攻击的成功率。

⑧大量的防护等级:这可能会使得开发人员搞不清每一种防护等级对应哪种防护。开发者们使用的厂商提供的IDE往往会隐藏CRP细节,使得用户不清楚他们使用的CRP防护等级。

⑨分离的On-Chip Debug(OCD)和CRP机制:在许多芯片如Renesas V850,78K0R和78K0,或者TI MSP430上,读保护机制和OCD权限是不相关的,使得用户需要通过软件或者保险丝来保护。由于这一模糊性,开发人员可能会注意不到某一种对芯片内存的读取方式,最终使得其它所有防护都无效化。

⑩复杂的bootloader逻辑:每一种bootloader的通讯协议都会增加攻击者可以攻击的面的宽度,导致引入更多的软件风险。例如,特定LPC芯片的USB存储仿真,其中包含一个FAT文件系统,可能会引出更多的问题,反观STM8芯片,一旦CRP被启用,所有bootloader指令都会被禁用。此外,一些Renesas芯片在一个bootloader里支持三种通讯接口,UART,single-wire UART和SPI,这极大地增加了攻击面宽度。

参考文献

[1]Jan Van den Herrewegen, David F. Oswald, Flavio D. Garcia, Qais Temeiza:Fill your Boots: Enhanced Embedded Bootloader Exploits via Fault Injection and Binary Analysis. IACR Trans. Cryptogr. Hardw. Embed. Syst. 2021(1): 56-81 (2021).



等价类内存参数
本作品采用《CC 协议》,转载必须注明作者和本文链接
源码分析1、LLVM编译器简介LLVM 命名最早源自于底层虚拟机的缩写,由于命名带来的混乱,LLVM就是该项目的全称。LLVM 核心库提供了与编译器相关的支持,可以作为多种语言编译器的后台来使用。自那时以来,已经成长为LLVM的主干项目,由不同的子项目组成,其中许多是正在生产中使用的各种 商业和开源的项目,以及被广泛用于学术研究。
双电压毛刺的故障攻击,侧信道史上首次!
Tips:DLL 和 Shellcode 文件路径使用绝对路径;不论是 list 操作还是 inject 操作,都会尝试开启 DEBUG 权限;避免对同一进程交替进行 DLL 注入和 shellcode 注入或者重复进行 DLL 注入,可能会报错 “被调用的对象已与其客户端断开连接。”,貌似是多次调用后远程接口会被释放掉;如果报错 “不支持此接口 ”,就多试几遍;并不是任何进程都能注入,只能对 list 动作显示出来的进程进行注入技术原理。
这里建议doc文档,图片可以贴的详细一些。爆破完好了,一样的6。想给它一个清晰完整的定义其实是非常困难的。
一、漏洞挖掘的前期–信息收集 虽然是前期,但是却是我认为最重要的一部分; 很多人挖洞的时候说不知道如何入手,其实挖洞就是信息收集+常规owasp top 10+逻辑漏洞(重要的可能就是思路猥琐一点),这些漏洞的测试方法本身不是特别复杂,一般混迹在安全圈子的人都能复现漏洞。接下来我就着重说一下我在信息收集方面的心得。
涉及系统命令调用和执行的函数在接收用户的参数输入时未做检查过滤,或者攻击者可以通过编码及其他替换手段绕过安全限制注入命令串,导致执行攻击指定的命令。
在近些年网络空间安全形势愈发严峻的情况下,对网络协议分析提出了越来越高的要求,其中,对未知协议分类分析更是亟需攻克的难点。针对未知协议的分类问题,提出一种基于层次聚的多策略未知协议分类方法。
Java安全之反射
2022-11-22 10:36:15
前言关于Java安全,反序列化漏洞一直是一个热门话题,而反序列化漏洞?可以从反射开始说起。通过反射,对象可以通过反射获取他的可以通过反射拿到所有?附加上动态特性。入门有以下三种方法获取?个“”,也就是java.lang.Class对象://1、通过对象调用 getClass() 方法来获取,通常应用在:比如你传过来一个 Object类型的对象,而我不知道你具体是什么,用这种方法
Webshell 检测综述
2022-12-15 09:45:32
通过Webshell,攻击者可以在目标服务器上执行一些命令从而完成信息嗅探、数据窃取或篡改等非法操作,对Web服务器造成巨大危害。Webshell恶意软件是一种长期存在的普遍威胁,能够绕过很多安全工具的检测。许多研究人员在Webshell检测领域进行了深入研究,并提出了一些卓有成效的方法。本文以PHP Webshell为例。
一颗小胡椒
暂无描述