滥用调试功能造成隐私泄露
如今,处理器一直配备有调试功能,以便于程序分析。具体来说,ARM调试架构包括一系列CoreSight组件和调试寄存器,以帮助系统调试,并设计了一组调试验证信号来限制这些组件和寄存器的使用。同时,调试功能的安全性也受到了审查,因为在传统的调试模型中使用这些功能通常需要物理访问。然而,自ARMv7以来,ARM引入了一种不需要物理访问的新调试模型,这加剧了我们对调试功能安全性的担忧。在本文中,我们对ARM调试功能进行了全面的安全分析,并总结了其安全性和漏洞含义。
为了了解影响,我们还调查了不同产品领域(即开发板、物联网设备、云服务器和移动设备)中的一系列基于ARM的平台。我们认为,分析和调查暴露了一个新的攻击面,它普遍存在于基于ARM的平台中。为了验证我们的担忧,我们进一步策划了NAILGUN攻击,该攻击获取敏感信息(例如,AES加密密钥和指纹图像),并通过滥用调试功能,在高特权模式和低特权模式下实现任意有效载荷执行。这种攻击并不依赖于软件漏洞,我们的实验表明,我们调查的几乎所有平台都容易受到攻击。从ARM生态系统的不同角度讨论了潜在的缓解措施。
如今,大多数处理器都使用调试体系结构来促进片上调试。例如,x86体系结构提供了六个调试寄存器来支持硬件断点和调试异常[32],而英特尔处理器跟踪[33]是一种硬件辅助调试功能,在最近的研究中引起了关注[65],[73]。ARM架构的处理器既有调试状态,也有非调试状态,设计了一组调试寄存器来支持自主机调试和外部调试[4],[5]。同时,ARM还引入了硬件组件,如嵌入式跟踪宏单元[9]和嵌入式交叉触发器[8],以支持各种硬件辅助调试目的。
相应地,硬件供应商通过芯片调试端口向外部调试器公开上述调试功能。最著名的调试端口之一是IEEE标准1149.1[31]定义的联合测试行动组(JTAG)端口,该端口旨在支持调试目标和外部调试工具之间的通信。带有JTAG端口和外部调试工具(例如,Intel System Debugger[34]、ARM DS-5[7]和OpenOCD[53]),开发人员能够高效方便地访问目标的内存和寄存器。
为了在不同的使用场景中授权外部调试工具,ARM设计了几种身份验证信号。具体而言,当目标处理器处于不安全或安全状态时,四个调试验证信号控制是否禁止非侵入性调试或侵入性调试(见第II-B节)。例如,一旦通过调试验证接口禁用了安全侵入性调试信号,外部调试工具将无法出于调试目的停止在安全状态下运行的处理器。在此管理机制中,将忽略外部调试器的当前权限模式。
尽管调试架构和身份验证信号已经提出多年,但它们的安全性仍受到社区的审查,因为在传统调试模型中使用这些功能通常需要物理访问。然而,自ARMv7[4]以来,ARM引入了一种不需要物理访问的新调试模型。如图1左侧所示,在传统的调试模型中,片外调试器通过JTAG接口连接到片上调试访问端口(DAP),DAP进一步帮助调试器调试片上处理器。在该模型中,片外调试器是调试主机,片上处理器是调试目标。图1的右侧展示了自ARMv7以来引入的新调试模型。在该模型中,使用内存映射接口将调试寄存器映射到内存中,以便片上处理器也可以访问DAP。因此片上处理器可以充当调试主机并调试同一芯片上的另一处理器(调试目标);我们将此调试模型称为处理器间调试模型。然而,ARM没有为新的调试模型提供权限管理机制的升级,并且在处理器间调试模型中仍然使用遗留的调试验证信号,这加剧了我们对调试功能安全性的担忧。
在本文中,我们深入研究了ARM调试体系结构,以全面了解其调试特性,并总结其安全含义。我们注意到,调试验证信号只考虑调试目标的特权模式,而忽略调试主机的特权模式。它在传统的调试模型中运行良好,因为在该模型中,调试主机是片外调试器,并且调试主机的特权模式与调试目标无关。然而,在处理器间调试模型中,调试主机和调试目标位于同一芯片,共享相同的资源(例如,内存和寄存器),并且重用相同的调试验证机制会通过滥用调试功能导致权限升级。在另一个处理器的帮助下,低特权处理器可以获得对高特权资源(如代码、存储器和寄存器)的任意访问。注意,本文中的低权限主要是指内核级别的权限,而高权限是指TrustZone[12]提供的安全权限级别和系统管理程序级别的权限。
此权限提升取决于调试身份验证信号。然而,ARM没有提供控制这些认证信号的标准机制,并且这些信号的管理高度依赖于片上系统(SoC)制造商。因此,我们进一步对不同基于ARM的平台中的调试认证信号进行了广泛的调查。具体而言,我们调查了由各种SoC制造商提供动力的设备上这些信号的默认状态和管理机制,目标设备涵盖四个产品领域,包括开发板、物联网(IoT)设备、商业云平台和移动设备。
在我们的调查中,我们发现调试验证信号在所调查的平台上完全或部分启用。同时,这些信号的管理机制要么没有记录在案,要么没有完全发挥作用。基于这一结果,我们设计了一个新的攻击场景,我们称之为NAILUN1。NAILGUN在低特权模式下运行的处理器上工作,并通过上述新的调试模型无限制地访问系统的高特权内容。具体而言,使用NAILGUN,低特权处理器可以跟踪高特权执行,甚至可以在高特权模式下执行任意有效载荷。为了证明我们的攻击,我们在具有不同SoC和架构的商用设备上实现了NAILGUN,实验结果表明,NAILGUN能够打破ARM架构强制执行的特权隔离。我们的在华为Mate 7上的实验也表明,NAILGUN可以从商用手机中泄露TrustZone中存储的指纹图像。此外,我们从ARM生态系统的不同角度提出了针对我们攻击的潜在对策。请注意,调试身份验证信号不能简单地禁用以避免攻击,我们将在第六节中对此进行讨论。
我们的研究结果已报告给相关硬件制造商,包括树莓派 PI基金会[58]等物联网设备供应商,miniNode[47]、Packet[55]、Scaleway[63]等商业云提供商,以及摩托罗拉[49]、三星[60]、华为[27]、小米[72]等移动设备供应商。同时,SoC制造商会收到其客户(例如移动设备供应商)的通知,并与我们合作寻求实用的解决方案。我们还向ARM通报了安全隐患。
硬件调试功能已经在现代处理器上部署了多年,但由于在大多数情况下需要物理访问,因此对这些功能的安全性没有给予足够的关注。然而,在我们的分析中,当涉及多处理器系统和处理器间调试模型时,它很容易受到攻击。我们认为这是一个典型的例子,在这个例子中,新的和先进的系统的部署会影响遗留机制的安全性。本文的目的是重新思考调试功能的安全设计,并激励研究人员/开发人员更多地关注现有系统中的“已知安全”或“假定安全”组件。
我们深入研究了ARM调试体系结构,以全面了解调试功能,并总结了漏洞的含义。据我们所知,这是第一次对ARM调试架构进行安全性研究。
我们研究了不同产品领域中的一系列基于ARM的平台,以检查它们在调试架构方面的安全性。结果表明,这些平台中的大多数都是易受攻击的。
我们暴露了一个普遍存在于基于ARM的设备中的潜在攻击面。它与软件错误无关,只依赖于ARM调试架构。
我们实现了NAILGUN攻击,并证明了该攻击在不同ARM架构和平台上的可行性,包括64位ARMv8Juno板、32位ARMv8 Raspberry PI3模块B+和ARMv7华为Mate 7。为了扩展攻击的广度,我们基于非侵入性和侵入性调试功能设计了不同的攻击场景。通过实验,我们发现NAILGUN可以在高特权模式下导致任意有效载荷执行,并在商用手机中泄露来自可信执行环境(TEE)的敏感信息。
我们从ARM生态系统的不同角度提出了应对我们攻击的对策。
图2显示了ARM生态系统中角色之间的关系。ARM设计SoC基础设施和处理器架构,并实现Cortex系列等处理器。在ARM的设计和许可下,SoC制造商,如高通公司,开发了集成ARM处理器或一些遵循ARM架构自行设计的处理器的芯片(如Snapdragon系列)。原始设备制造商(如三星和谷歌)从SoC制造商那里获得这些芯片,并为最终用户生产PC和智能手机等设备。
请注意,生态系统中的角色可能重叠。例如,ARM开发自己的SoC,就像Juno板一样,三星也扮演着SoC制造商的角色,开发Exynos SoC。
ARM体系结构定义了侵入式和非侵入式调试功能[4]、[5]。侵入式调试被定义为可以控制和观察处理器的调试过程,而非侵入式调试只涉及观察而没有控制。断点和软件步进等调试功能属于侵入性调试,因为它们用于停止处理器并修改其状态,而跟踪(通过嵌入式跟踪宏单元)和监视(通过性能监视器单元)等调试功能则属于非侵入性调试。
侵入式调试可以在两种不同的模式下执行:停止调试模式和监视器调试模式。在停止调试模式中,当调试事件(例如,硬件断点)发生时,处理器停止并进入调试状态。在调试状态下,处理器停止执行由程序计数器指示的指令,并且调试器(诸如另一处理器的片上组件或诸如JTAG调试器的片外组件)可以检查并通过调试访问端口(DAP)修改处理器状态。在监视器调试模式下,当调试事件发生时,处理器将执行调试异常,而不是停止。一种被称为监视器的特殊软件可以控制并相应地改变过程状态。
ARM定义了四个用于外部调试验证的信号,即DBGEN、NIDEN、SPIDEN和SPNIDEN。DBGENsignal控制系统中是否允许进行非安全侵入性调试。当信号DBGEN或NIDEN为高时,启用非安全非侵入性调试。类似地,SPIDEN信号和SPNIDEN信号分别用于控制安全侵入性调试和安全非侵入性调试。请注意,这些信号只考虑调试目标的特权模式,而忽略了调试主机的特权模式。
在ARM生态系统中,ARM只设计这些信号,但没有指定控制这些信号的标准。通常,SoC制造商负责设计管理这些信号的机制,但不同SoC中的管理机制可能不同。原始设备制造商负责采用管理机制来配置(即禁用/启用)其生产设备中的认证信号。
ARM CoreSight体系结构[6]为复杂SoC的调试和跟踪提供了解决方案,ARM在CoreSight架构下设计了一系列硬件组件。本文主要使用CoreSight嵌入式跟踪宏单元和CoreSight嵌入交叉触发器。
嵌入式跟踪宏单元(ETM)[9]是一种非侵入性调试组件,使开发人员能够通过监控指令和数据总线来跟踪指令和数据,而对性能的影响较小。为了避免严重的性能影响,ETM在不同ARM处理器上的功能各不相同。
嵌入式交叉触发器(ECT)[8]由交叉触发器接口(CTI)和交叉触发器矩阵(CTM)组成。它使CoreSight组件能够在彼此之间广播事件。CTI收集并映射触发请求,并将其广播到ECT子系统上的其他接口。CTM连接到至少两个CTI和其他CTM以在它们之间分配触发事件。
ARM安全扩展[12],即TrustZone技术,允许处理器在安全和不安全状态下运行。存储器还被划分为安全区域和非安全区域,使得安全存储器区域仅可由在安全状态下运行的处理器访问。
在ARMv8体系结构[5]中,处理器的权限取决于其当前的异常级别(EL)。EL0通常用于用户级应用程序,而EL1是为内核设计的,EL2是为系统管理程序保留的。EL3充当安全状态和非安全状态之间的看门人,并拥有系统中的最高权限。安全和非安全状态之间的切换仅发生在EL3中。
如第II-B节所述,ARM架构中提供了非侵入式调试和侵入式调试。在本节中,我们仔细研究了技术参考手册(TRM)[4]、[5]中记录的非侵入性和侵入性调试机制,并揭示了手册中指出的漏洞和安全隐患。请注意,我们假设在本节中启用了所需的调试验证信号,并且在下面的第四节中证明了这一假设是合理和实用的。
非侵入式调试不允许停止处理器并自检处理器的状态。相反,非侵入性功能,如性能监视器单元(PMU)和嵌入式跟踪宏单元(ETM),分别用于计数处理器事件和跟踪执行。
在ARMv8体系结构中,PMU由一组在非安全EL1中可访问的寄存器控制。然而,我们发现ARM允许PMU监视EL2中触发的事件,即使NIDEN信号被禁用【在ARMv7中,NIDEN需要使PMU监视处于不安全状态的事件】。此外,PMU可以监视在安全状态下触发的事件,包括启用了SPNIDEN信号的EL3。换句话说,具有非安全EL1权限的应用程序能够在调试验证信号的帮助下监视EL2中触发的事件和安全状态。在ARMv8中引入了MDCR寄存器的TPMbit,以限制对低EL中的PMU寄存器的访问。然而,此限制仅适用于系统寄存器接口,而不适用于内存映射接口[5]。
ETM用一组配置寄存器跟踪目标处理器的指令和数据流。类似于PMU,ETM能够分别用NIDEN和SPNIDEN信号跟踪非安全状态(包括EL2)和安全状态的执行。然而,它只需要不安全的EL1来访问ETM的配置寄存器。与上述对访问PMU寄存器的限制类似,由CPTR寄存器的TA位实施的基于硬件的保护也仅适用于系统寄存器接口[5]。
总之,非侵入式调试功能允许具有低权限的应用程序了解有关高权限执行的信息。
含义1:低特权模式下的应用程序能够通过PMU和ETM了解有关高特权执行的信息。
侵入式调试允许外部调试器停止目标处理器并访问处理器上的资源。图3显示了一个典型的侵入式调试模型。在侵入式调试的场景中,我们有一个外部调试器(HOST)和调试目标处理器(target)。为了开始调试,HOST通过ECT向TARGET发送调试请求。一旦处理了请求,HOST和TARGET之间的通信就通过调试架构提供的指令传输和数据通信通道(详见第III-B2节)来实现。最后,重新启动请求用于结束调试会话。在该模型中,由于HOST始终被视为外部调试设备或通过JTAG端口连接的工具,因此我们通常认为它需要物理访问才能调试TARGET。然而,自ARMv7以来,ARM引入了一种处理器间调试模型,允许片上处理器在没有任何物理访问或JTAG连接的情况下调试同一芯片上的另一个处理器。此外,仅考虑TARGET的特权模式而忽略HOST的特权方式的遗留调试认证信号用于进行处理器间调试模型的特权控制。在本节中,我们将讨论遗留调试身份验证机制下的进程间调试的安全含义。
1、进入和现有调试状态:为了在TARGET中实现侵入式调试,我们需要使TARGET在调试状态下运行。在调试状态下运行的处理器通过外部调试接口进行控制,并且它停止从程序计数器指示的位置执行指令。有两种典型的方法可以使处理器进入调试状态:在处理器上执行HLT指令或通过ECT发送外部调试请求。
HLT指令被广泛用作软件断点,执行HLT指令直接导致处理器停止并进入调试状态。进入调试状态的更通用方法是通过ECT发送外部调试请求。多处理器系统中的每个处理器都嵌入了一个单独的CTI(即ECT接口),并且存储器映射接口使处理器上的CTI可用于其他处理器。因此,HOST可以利用TARGET的CTI来发送外部调试请求,并使TARGET进入调试状态。类似地,可以使用重新启动请求来退出调试状态。
但是,外部调试请求没有考虑HOST的特权;这种设计允许一个低特权处理器来制造一个高特权处理器进入调试状态。例如,在不安全状态下运行的HOST可以使在安全状态下的TARGET进入启用SPIDEN的调试状态。类似地,非安全EL1中的HOST可以在启用DBGENE的情况下停止EL2中的TARGET。
含义2:低特权处理器可以通过ECT使任意处理器(甚至是高特权处理器)进入调试状态。
2、调试指令传输/通信:尽管TARGET的正常执行在进入调试状态后暂停,但外部调试指令传输寄存器(EDITR)使TARGET能够在调试状态下执行指令。每个处理器都拥有一个单独的EDITR寄存器,当处理器处于调试状态时,将一条指令(分支指令等特殊指令除外)写入该寄存器会使处理器执行该指令。
同时,调试通信信道(DCC)允许在正常状态下的HOST和调试状态下的TARGET之间进行数据传输。在ARMv8体系结构中,DCC中存在三个寄存器。32位DBGDTRTX寄存器用于将数据从TARGET传输到HOST,而32位DBGDTRRX寄存器用于从HOST接收数据。此外,64位DBGDTR寄存器可用于通过单个寄存器在两个方向上传输数据。
我们注意到,EDITR寄存器中指令的执行仅取决于TARGET的权限,而忽略了HOST的权限。HOST实际上允许低权限处理器通过处理器间调试访问高权限资源。假设TARGET在安全状态下运行,HOST在非安全状态下运转,HOST能够要求TARGET通过EDITR寄存器读取安全存储器,并通过DBGDTRTX寄存器进一步获取结果。
含义3:在处理器间调试中,TARGET中的指令执行和资源访问不考虑HOST的权限。
3、 特权升级:含义2和含义3表示低特权HOST可以通过高特权TARGET访问高特权资源。然而,如果TARGET保持在低特权模式,则对高特权资源的访问仍然受到限制。ARM提供了一种在调试状态下升级权限的简单方法。仅在调试状态下可用的dcps1、dcps2和dcps3指令可以直接将处理器的异常级别分别提升为EL1、EL2和EL3。
dcps指令的执行没有权限限制,也就是说,无论安全或非安全状态如何,它们都可以在任何异常级别执行。这种设计使在调试状态下运行的处理器能够在没有任何限制的情况下实现任意权限。
含义4:权限提升指令使运行在调试状态下的处理器能够在没有任何限制的情况下获得高权限。
非侵入式和侵入式调试都涉及允许外部调试器访问高权限资源的设计,同时启用某些调试验证信号,并且忽略调试器的权限模式。在HOST是片外的传统调试模型中,这是合理的,因为片外平台的特权模式与TARGET所在的片上平台的特权方式无关。然而,由于ARM允许片上处理器充当外部调试器,因此在传统调试模型中简单地重用调试验证信号的规则会使片上平台容易受到攻击。
非侵入性调试:图4显示了通过非侵入性的调试来违反权限隔离的想法。单个处理器的执行被划分为不同的特权模式,并强制隔离以保护高特权模式下的敏感计算不受低特权应用程序的影响。然而,根据含义1,低权限应用程序可以通过一些简单的步骤来违反这种隔离。图4中的步骤1使低权限应用程序的ETM跟踪能够为违规做准备。接下来,我们在步骤中触发敏感计算,将处理器切换到高特权模式。由于ETM在步骤1中启用,因此会记录步骤3中有关敏感计算的信息。一旦计算完成,处理器返回到低特权模式,并且低特权应用程序在步骤4中禁用跟踪。最后,通过分析步骤5中的跟踪输出,揭示了关于敏感计算的信息。
入侵调试:关于入侵调试,含义2-4在处理器间调试模型中是不可忽略的,因为HOST和TARGET在同一平台上工作,共享同一资源(如内存、磁盘、外围设备等)。如图5(a)所示,系统由高特权资源、低特权资源和双核集群组成。默认情况下,群集中的两个处理器只能访问低权限资源。为了实现对高特权资源的访问,处理器A充当外部调试器,并向处理器B发送调试请求。在图5(B)中,处理器B由于请求而进入调试状态,如含义2中所述。但是,两个处理器都无法访问高权限资源,因为它们都仍在运行在低特权模式下。接下来,如图5(c)所示,处理器A使处理器B执行权限提升指令。处理器B然后进入高特权模式,并根据含义4获得对高特权资源的访问。此时,仍然禁止从处理器A访问高特权资源。最后,由于处理器A能够从处理器B获取数据,并且处理器B可以直接访问高特权资源,如含义3所示,因此低特权处理器A实际上获得了对高特权资源的间接访问,如图5(d)所示。
与传统的调试模型不同,图4中的非侵入式调试和图5中的侵入式调试不需要物理访问或JTAG连接。
只有在启用某些调试身份验证信号时,才会发生上述隔离冲突和权限提升。因此,这些信号的状态对真实世界设备的安全性至关重要,这导致我们对真实世界的设备中调试验证信号的默认状态进行调查。此外,我们还对部署在真实世界设备上的调试验证信号的管理机制感兴趣,因为该机制可以用于在运行时改变信号的状态。此外,由于这种状态和管理机制高度依赖于SoC制造商和原始设备制造商,我们选择了由不同SoC和原始设备商供电的各种设备作为调查目标。为了全面起见,我们还调查了应用于不同产品领域的设备,包括开发板、物联网(IoT)设备、商业云平台和移动设备。我们在第IV-A节中讨论了我们对目标设备的选择,并在第IV-B节和第IV-C节中介绍了调查结果。
基于ARM的开发板广泛用于构建安全相关分析系统[15],[25],[28],[68],[77]。然而,开发委员会本身的安全性并没有得到很好的研究。因此,我们选择了广泛使用的开发板[15]、[68]、[77]、i.MX53快速启动板(QSB)[52]作为我们的分析对象。作为比较,本文还研究了ARM官方发布的Juno Board[10]。
低功耗使ARM架构成为物联网(IoT)设备的自然选择。许多传统硬件供应商开始提供基于ARM的智能家居解决方案[3]、[46]、[59],经验丰富的开发人员甚至基于廉价的SoCs[26]构建自己的低成本解决方案。作为一个典型的例子,Raspberry PI 3[58]被选为我们的目标,截至2018年3月,该产品已售出9000多台[57]。
云计算领域以x86架构为主,然而,ARM架构中高通量计算的优势开始引起包括微软在内的大型云提供商的注意[70]。尽管大多数基于ARM的云服务器仍在测试中,但我们使用公开可用的服务器进行分析,包括miniNodes[47]、Packet[55]和Scaleway[63]。
目前,市场上大多数移动设备都采用ARM架构,移动设备供应商基于各种SoC制造商提供的SoC构建设备。例如,华为和三星分别为自己的移动设备设计了Kirin[27]和Exynos[60]SoC。同时,高通[56]和联发科[45]为各种移动设备供应商提供SoC[48]、[49]、[72]。考虑到移动供应商的市场份额[67]和SoC的多样性,我们选择谷歌Nexus 6、三星Galaxy Note 2、华为Mate 7、摩托罗拉E4 Plus和小米Redmi 6作为我们的分析目标。
调试身份验证状态寄存器(DBGAUTHSTATUS)是EL1中可访问的只读寄存器,该寄存器的位[0:7]反映认证信号。对于目标设备,我们构建了一个可加载内核模块(LKM),通过该寄存器读取调试验证信号的状态。然而,移动设备中的一些库存ROM禁止加载LKM。在这种情况下,我们获得库存ROM的内核源代码,并使用LKM启用选项重新编译内核映像。重新编译的图像随后被闪回到设备以进行调查。请注意,我们不对内核中的其他功能进行更改,并且内核替换不会影响身份验证信号的状态。
表I总结了测试设备中调试验证信号的默认状态。在仅为开发目的设计的Juno板上,默认情况下,调试验证信号都处于启用状态。然而,我们惊讶地发现,在Raspberry PI 3 Model B+、华为Mate 7、摩托罗拉E4 Plus和小米Redmi等商用设备上,所有调试验证信号都是默认启用的。此外,所有被调查的云平台也启用了所有这些信号。其他平台上的结果显示,在测试的移动设备中,调试验证信号在默认情况下部分启用。
对于启用SPNIDEN和SPIDEN的手机,我们还调查了TrustZone在这些设备上的使用情况。根据[2]、[24]、[62],华为Mate 7、摩托罗拉E4 Plus和小米Redmi 6利用TrustZone对采集的指纹图像实施硬件级别的保护。通过人工自检华为Mate 7中TEE的二进制图像,我们还发现TEE内部存在加密引擎。摩托罗拉E4 Plus和小米Redmi 6的TEE图像表明,它们都使用ARM可信固件(ATF)[11]作为TEE操作系统。ATF同时支持可信引导和可信应用程序,我们还在这些二进制文件中发现了一个潜在的安全补丁模块。在小米Redmi 6的TEE图像中,我们识别了一个具有成对文件名和128位校验和的大型阵列,该阵列可用于验证系统文件的完整性。
为了了解部署的信号管理机制,我们从公开的TRM和硬件供应商发布的源代码中收集信息。Juno板和i.MX53 QSB上的信号管理机制部分记录在TRM中,我们还在摩托罗拉Nexus 6和华为Mate 7的内核源代码中确定了一些潜在的相关代码。关于其他平台,无法从公开的TRM和发布的源代码中识别信号管理机制。
NXP i.MX53快速启动板(QSB)。根据i.MX53 SoC[51]的公开可用TRM,DBGEN信号由位于存储器地址0x63FA0004的ARM_GPC寄存器的DBGEN位控制,并且没有指定访问该寄存器的特权要求。其他调试验证信号的管理没有记录在案。在进一步的实验中,我们发现SPIDEN和SPNIDEN信号可以通过JTAG端口进行控制。一旦我们使用JTAG通过额外的调试软件(ARM DS-5[7]或OpenOCD[53])连接到板上,SPIDEN信号和SPNIDEN信号就会直接启用。请注意,这种机制实际上破坏了ARM的设计目的,因为它允许调试器启用调试验证信号,而这些信号是为限制调试器的使用而设计的。
ARM Juno r1板。作为ARM发布的官方开发平台,调试认证信号的管理机制在Juno Board的TRM中有很好的记录[10]。开发人员可以通过系统配置控制器(SCC)或系统安全控制(SSC)寄存器中的调试验证寄存器来控制信号。SCC实际上是由配置MircoSD卡中的文本文件管理的,卡上的配置是在早期板设置期间由主板微控制器固件加载的;对文本文件的修改在重新启动后生效。此配置MircoSD卡不可用于芯片上操作系统,并且可以通过专用USB电缆安装到远程PC。相反,SSC寄存器可以在运行时进行修改,并且只有当处理器在安全状态下运行时才能访问它们。在我们的实验中,我们发现SCC中的调试认证寄存器只能用于管理SPIDEN和SPNIDEN信号。清除寄存器的位0(记录为“全局外部调试启用”位)不会禁用任何调试验证信号。类似地,SSC寄存器可以控制SPIDEN和SPNIDEN信号的状态,但是对DBGEN和NIDEN的修改不起作用。与上述i.MX53QSB不同,通过JTAG连接到外部调试软件将不会启用SPIDEN和SPNIDEN信号。
摩托罗拉Nexus 6。我们检查了安卓开源项目(AOSP)提供的摩托罗拉Nexus 6的内核源代码,发现调试验证信号由地址为0xFC4BE024的CoreSight保险丝[64]控制。由于熔断器被认为是一次性可编程(OTP)器件,因此直接写入相应的存储器失败,而不会提供任何错误消息。
华为Mate 7。华为Mate 7的内核源代码在华为开源发布中心发布[30]。从源代码中,我们发现DBGEN信号由位于地址0xFFF0A82C的寄存器控制。然而,直接读取/写入此寄存器会导致严重故障,导致手机重新启动。我们认为,出于安全考虑,华为已经采取了额外的保护措施来阻止访问该注册。
我们的调查表明,默认情况下,所有测试设备上的调试身份验证信号都是完全或部分启用的,这使得它们容易受到上述隔离违规和权限升级的影响。此外,除了开发板之外,所有测试设备上都没有针对这些信号的公开管理机制,开发板的记录管理机制要么不完整(i.MX53 QSB),要么功能不全(Juno Board)。一方面,不可用管理机制可以帮助防止对调试认证信号的恶意访问。另一方面,它还阻止用户出于防御目的禁用调试验证信号。
为了验证第三节中总结的安全含义和第四节中描述的调试验证信号的发现,我们设计了一个名为NAILGUN的攻击,并在几个不同的平台上实现。NAILGUN滥用ARM体系结构中的非侵入性和侵入性调试功能,从低特权模式获得对高特权资源的访问权限。为了进一步理解攻击,我们分别为侵入式调试和非侵入式设计了两种攻击场景。NAILGUN具有非侵入性调试功能,能够推断AES加密密钥,通过在非安全EL1中执行应用程序。关于侵入式调试功能,NAILGUN演示了在不安全EL1中运行的应用程序可以在EL3中执行任意有效负载。为了了解NAILUN对真实世界设备的影响,我们展示了NAILUN可以用于提取华为Mate 7中TEE保护的指纹图像。可以从EL1发起类似的攻击来攻击EL2。由于有三种主要的ARM架构(即ARMv7、32位ARMv8和64位ARMv7),我们也在这些不同的架构上实现了NAILGUN,并讨论了实现中的差异。
在我们的攻击中,我们不假设操作系统的版本或类型,也不依赖软件漏洞。在硬件方面,NAILGUN不限于任何特定的处理器或SoC,并且能够在各种基于ARM的平台上工作。此外,不需要对平台进行物理访问。
在非侵入性调试攻击中,我们假设SPNIDEN或NIDEN信号被启用,分别攻击安全状态或非安全状态。我们还对入侵调试攻击中的SPIDEN和DBGEN信号进行了类似的假设。我们进一步假设入侵调试攻击中的目标平台是多处理器平台。此外,我们的攻击需要访问CoreSight组件和调试寄存器,这些组件和寄存器通常映射到系统中的一些物理内存区域。请注意,将CoreSight组件和调试寄存器映射到虚拟内存地址空间通常需要非安全EL1权限。
AES算法已被证明易受各种攻击[35]、[36]、[41]、[42]、[43]、[69]。密钥漏洞是基于表查找的实现,该实现旨在提高AES的性能,泄漏有关加密密钥的信息。通过访问的表项的地址,攻击者可以有效地重建加密密钥。在这种攻击中,我们假设有一个安全应用程序在TrustZone中运行,该应用程序持有AES加密密钥,并且该安全应用程序还提供了一个到非安全操作系统的接口来加密给定的明文。非安全操作系统无法直接读取加密密钥,因为TrustZone强制隔离安全状态和非安全状态。我们的目标是通过从非安全操作系统调用加密接口来揭示存储在安全内存中的加密密钥。
图4中描述的违反权限隔离使非安全应用程序能够了解有关安全执行的信息。具体来说,ETM指令跟踪帮助重建执行指令的地址,而ETM数据地址跟踪记录数据处理指令中涉及的数据的地址(例如ldr、str、mov等)。了解执行表查找的指令地址范围并从跟踪输出中识别表的内存地址是很简单的,这进一步有助于检索具有记录数据地址的加密密钥。请注意,我们需要的唯一信息是AES算法访问的表项的索引。因此,为了简化分析并减少噪声,我们可以使用ETM中的地址范围滤波器来仅跟踪执行表查找的地址范围。
为了演示攻击,我们首先在NXP i.MX53快速启动板上构建一个裸机环境[52]。该板与单个Cortex-A8处理器集成,可实现数据地址跟踪,我们基于开源项目[75]构建环境,该项目可实现安全和非安全状态之间的切换和通信。接下来,我们将OpenSSL 1.0.2n[54]的AES加密算法移植到环境中,并使用存储在安全存储器中的预定义128位密钥使其在安全状态下运行。非安全应用程序可以使用smc指令和寄存器r0中的明文指针请求安全加密。
图6展示了我们的攻击过程。我们使用随机的128位输入作为步骤1中加密的明文,相应的密文记录在步骤2中。从ETM跟踪流中,我们对每个加密回合中访问的表条目的地址进行解码,并通过表的基地址将其转换为条目的索引,如步骤3中所示。对于索引和密文,反转AES加密算法并计算步骤4中的圆形密钥是微不足道的。最后,使用第1轮中的加密密钥和访问的表条目,NAILGUN对步骤5中的原始加密密钥进行解码。源代码的关键部分包含在附录A中。
注意,以前对AES算法的侧信道攻击需要使用不同明文进行数百次甚至数千次运行,以耗尽不同的可能性。NAILGUN能够通过单次运行任意明文来揭示AES加密密钥。
侵入式调试比非侵入式调试更强大,因为我们可以通过调试体系结构停止目标处理器并访问受限制的资源。图5显示了使用侵入式调试的权限提升的简要概念,我们进一步扩展了实现任意有效负载执行的想法。
EDITR寄存器使攻击者能够从HOST在TARGET上执行指令。但是,并非所有指令都可以通过EDITR寄存器执行。例如,在EDITR中执行分支指令(例如,b、bl和blr指令)会导致不可预测的结果。同时,现实世界中的恶意负载通常包含分支指令。为了绕过这一限制,NAILGUN制定了一种在高特权模式下执行任意有效载荷的稳健方法。
通常,我们认为恶意负载的执行应该满足三个基本要求:1)完整性。有效负载应在非调试状态下执行,以克服EDITR寄存器的指令限制。2) 高级特权。应使用比攻击者拥有的权限更高的权限执行负载。3) 稳健。有效载荷的执行不应影响其他程序的执行。
为了满足第一个要求,NAILGUN必须操纵TARGET中非调试状态的控制流。对于处于调试状态的处理器,DLR_EL0寄存器保存退出调试状态后要执行的第一条指令的地址。因此,对该寄存器的重写可以有效地劫持处于非bug状态的TARGET的指令控制流。
第二个要求很难满足。请注意,dcps指令的执行不会更改非调试状态的异常级别,这意味着我们需要在非调试状态下进行另一次权限提升,尽管HOST可以在调试状态下提升TARGET的权限。处于非调试状态的smc指令断言一个安全监视器调用(smc)异常,该异常将处理器带到EL3,我们可以利用此指令进入EL3。然而,在进入EL3之后,我们仍然需要将执行重定向到有效负载。在每个异常级别中,传入的异常都由相应异常向量中指定的处理程序处理。有鉴于此,我们操作异常向量,并将相应的异常处理程序重定向到有效负载。
第三个要求也是关键的,因为NAILGUN实际上修改了DLR_EL0所指向的指令和VBAR_EL3寄存器所指示的异常向量。为了避免操作带来的副作用,NAILGUN需要在有效载荷执行后回滚TARGET中的这些更改。此外,NAILGUN需要在有效载荷的最开始存储堆栈指针和通用寄存器的值,并在有效载荷结束时恢复它们。
我们在64位ARMv8 Juno r1板[10]上实现了NAILGUN,以表明含义2-4导致EL3中的任意有效载荷执行。该板包括两个CortexA57处理器和四个Cortex-A53处理器,我们使用ARM Trusted Firmware(ATF)[11]和Linaro在Juno[40]的OpenEmbedded Linux上的可交付成果,以构建既支持安全操作系统又支持非安全操作系统的软件环境。在ATF实现中,内存范围0xFF000000-0xFFDFFFFF被配置为安全内存,我们证明了我们可以将任意有效载荷复制到安全内存,并通过非安全EL1中的LKM执行它。
实现的源代码包含在附录B中,图7描述了整个攻击过程中TARGET的状态和内存变化。图中突出显示的红色表示更改的状态和内存。在图7(a)中,TARGET在执行mov指令之前由HOST停止。同时,VBAR_EL3指向EL3异常向量。由于SMC异常属于同步异常,并且Juno板使用64位架构实现EL3,因此相应的异常处理程序位于异常向量的偏移0x400处。图7(b)显示了退出调试状态之前TARGET的内存。NAILGUN将有效载荷复制到安全存储器,并将DLR_EL0所指向的指令更改为smc指令。此外,64位EL3同步异常处理程序中的第一条指令(由VBAR_EL3+0x400指示)被更改为以复制的有效载荷为目标的分支指令(b指令)。然后,HOST恢复TARGET,pc指向恶意smc指令,如图7(c)所示。smc指令的执行将TARGET带到如图7(d)所示的状态。由于smc指令已经执行,因此ELR_EL3寄存器的值是下一条指令的地址。我们对异常处理程序的操作会导致有效负载的执行,这既可以执行恶意活动,也可以恢复更改后的内存。在有效负载的末尾,利用eret指令切换回非安全状态。图7(e)显示了切换前的内存和状态,以及对非安全内存和EL3异常的更改向量被还原。此外,ELR_EL3寄存器也被操作以确保mov指令的执行。最后,在图7(f)中,TARGET再次进入非安全状态,内存和状态看起来与图7(a)中的相同。
图8显示了通过LKM在TrustZone中执行有效负载的示例。我们的有效负载包含一个最小化的串行端口驱动程序,以便NAILUN可以向串行端口发送输出。为了证明攻击成功,我们还从CurrentEL寄存器中提取当前异常级别。图8中的最后一行输出表明NAILGUN能够在EL3中执行任意代码,EL3拥有整个系统的最高权限。
为了了解NAILGUN对真实世界设备的影响,我们还展示了NAILGUN能够泄露存储在安全存储器中的敏感信息。目前,手机中最常用的安全功能之一是指纹认证[29]、[48]、[72],原始设备制造商将指纹图像存储在TrustZone中,以增强设备的安全性[2]、[24]、[62]。在本实验中,我们使用华为Mate 7[29]证明了在NAILGUN的帮助下,在非安全EL1中运行的LKM可以提取指纹图像。华为Mate 7由海思麒麟925 SoC供电,该SoC集成了四核Cortex-A5集群和四核Cortex-A7集群。FPC1020[20]指纹传感器用于Mate 7中捕获指纹图像。之所以选择这款手机,是因为FPC1020的产品规范[21]和驱动程序源代码[71]是公开的,这减少了实施攻击的工程工作量。
如前一个实验所示,NAILGUN提供了一种非安全EL1LKM,可以读取/写入任意安全/非安全内存。为了提取指纹图像,我们需要知道1)图像存储在哪里,2)图像数据的格式。
为了了解图像的位置,我们对映射到/dev/block/mmcblk0p10的TEE OS二进制图像进行反编译,并确定使用名为fpc1020_fetch_image的函数从指纹传感器读取图像。该函数以指向图像缓冲区的指针、指向缓冲区的偏移量和图像大小为参数,并将从传感器获取的指纹图像复制到图像缓冲区。经过进一步的反思,我们发现华为使用预先分配的大缓冲区来存储此图像,并且指向缓冲区头部的指针存储在固定的内存地址0x2efad510中。类似地,图像的大小被存储在固定的存储器地址0x2ef7f414处。根据地址和大小,我们使用NAILGUN提取图像数据。由于华为Mate 7和ARM Juno板中的ARM架构不同,NAILGUN的实现也不同(见第V-B4节)。本实验的源代码包含在附录C中。
FPC1020产品规范[21]中详细记录了图像数据的格式。根据规范,数据的每个字节指示单个像素的灰度级。因此,利用提取的图像数据,制作灰度指纹图像是微不足道的。图9显示了通过NAILGUN从华为Mate 7中提取的指纹图像,这一结果表明,经过一些工程努力,NAILGUN能够泄露商用手机TEE中的敏感数据。
在第三节中,我们讨论了64-32位ARMv8和ARMv7体系结构中存在类似的含义。然而,这些体系结构的实现之间也存在一些主要差异,我们将在下面讨论这些差异。
我们在Raspberry PI 3 Model B+和Motorola E4 Plus上实现了具有32位ARMv8的NAILGUN原型。在该架构中,停止处理器的步骤类似于64位ARMv8架构中的上述步骤,并且32位和64位ARMv4架构上的NAILGUN之间的主要区别在于使用了EDITR。在64位ARMv8中,我们直接将指令的二进制表示写入EDITR。但是,在32位ARMv8中,指令的前半部分和后半部分需要颠倒。例如,dcps3指令的二进制表示在64位和32位ARMv8中分别为0xD4A00003和0xF78F8003。在64位ARMv8体系结构中,我们通过将0xD4A000003写入EDITR,使处于调试状态的处理器执行此指令。但是,在32位ARMv8体系结构中,写入EDITR的指令应该是0x8003F78F,而不是0xF78F8003。
关于ARMv7,我们在华为Mate 7上实现了NAILGUN,如第V-B3节所述,在ARMv7和ARMv8架构上的NAILGUN有三个主要区别。首先,ECT不需要在ARMv7中停止和重新启动处理器。将1写入调试运行控制寄存器(DBGDRCR)的位[0]和位[1]可以分别直接停止和重新启动处理器。其次,EDSCR的ITRen位控制是否在ARMv7体系结构中启用EDITR。我们需要在进入调试状态后启用ITRen位,并在退出调试状态前再次禁用它。最后,在ARMv7体系结构中,cps指令是未定义的,我们需要更改当前程序状态寄存器(CPSR)的M位,以将处理器提升到监控模式来访问安全资源。
由于NAILGUN攻击仅在启用调试验证信号时有效,因此凭直觉禁用这些信号可以有效防御。然而,根据ARM体系结构参考手册[4]、[5]、第四节中的分析结果以及硬件供应商的响应,我们认为这些信号不能简单地禁用,因为存在以下挑战:
侵入式和非侵入式调试功能被大量用于构建分析系统[14]、[16]、[17]、[18]、[22]、[38]、[39]、[44]、[50]、[74]。禁用调试验证信号将直接使这些系统完全或部分发生故障。在ARMv7架构[4]中,情况甚至更糟,因为广泛使用的性能监控单元(PMU)[1]、[13]、[19]、[23]、[50]、[61]、[76]的功能也依赖于认证信号。由于上述大多数分析系统都试图执行恶意软件检测/分析,因此滥用调试功能导致的信息泄露或权限升级的风险大大增加(即,在这种情况下,调试架构是一把双刃剑)。
根据第IV-C节,在大多数测试平台中,调试验证信号的管理机制对公众不可用。在我们的调查中,许多SoC制造商对SoC的TRM保密;并且一些其他SoC的公开可用的TRM没有提供这些信号的完整管理机制,或者将它们与JTAG调试混淆。不可用的管理机制使得用户很难禁用这些信号。例如,开发人员使用树莓派等设备来构建自己的低成本物联网解决方案,而默认启用的身份验证信号使他们的设备面临通过NAILGUN远程攻击的风险。然而,由于缺乏可用的管理机制,即使他们已经注意到了风险,他们也无法禁用这些身份验证信号。
我们还注意到,许多经过测试的平台都使用fuse来管理身份验证信号。一方面,保险丝的一次性可编程特性防止了对调试验证信号的恶意覆盖。然而,另一方面,由于现有设备具有相同的一次性可编程功能,用户无法禁用这些信号以避免NAILUN。此外,先前的研究证明,保险丝本身容易受到硬件故障攻击[66]。
调试验证信号基于硬件而不是软件。因此,如果没有额外的硬件支持,就不能通过改变软件配置来简单地禁用信号。根据硬件供应商的回应,对调试验证信号部署额外的限制会增加产品线的成本。此外,禁用调试验证信号会禁止合法的调试过程,如产品召回后的修复或错误修复,这会给维护过程带来额外成本。
我们认为NAILGUN攻击是由两个原因引起的:1)ARM定义的调试验证信号没有充分考虑处理器间调试的场景,这导致了第三节中描述的安全隐患;2) 与原始设备制造商和云提供商相关的第IV-B节中描述的调试验证信号的配置,以及与SoC制造商相关的第IV-C节中所描述的管理机制,使NAILGUN攻击在现实世界的设备上可行。因此,本节中讨论的对策主要集中在调试验证信号的设计、配置和管理上。作为补充,我们还提供限制对调试寄存器的访问的防御,这可能会阻止NAILGUN的实现。总的来说,我们利用深度防御的概念,并建议在ARM生态系统中的不同角色之间进行全面防御。
驱动NAILGUN存在的关键问题是调试机制和验证信号的设计没有充分考虑新涉及的处理器间调试模型的场景。因此,重新设计它们并使它们考虑传统调试模式和处理器间调试模型之间的差异将完全消除安全隐患。具体来说,我们建议TARGET精确地检查HOST的类型。如果HOST是芯片外的(传统的调试模型),那么现有的设计是可以工作的,因为TARGET和HOST的执行平台是分开的(它们的权限不相关)。关于片上HOST(处理器间调试模型),应该需要更严格的限制。例如,在侵入式调试中,TARGET应检查HOST的权限,并且只有在HOST拥有与TARGET更高或相同的权限时才响应调试请求。类似地,执行dcps指令的请求也应该考虑HOST的特权。HOST永远不能发出将TARGET升级到高于当前HOST异常级别的异常级别的dcps指令。
除了区分芯片上和芯片外HOST之外,我们还建议提高认证信号的粒度。DBGEN和NIDEN信号用于控制整个非安全状态的调试功能,这为内核级(EL1)应用程序提供了利用管理程序级(EL2)执行的机会。因此,我们建议对这些信号进行细分。
从SoC制造商的角度来看,限制对这些信号的管理将是一种合理的防御。具体而言,访问调试验证信号的管理单元所需的特权应遵循该信号的功能,以避免恶意覆盖。例如,SPNIDEN和SPIDEN信号的管理单元应当仅限于安全访问。当前SoC设计的限制方法要么过于严格,要么过于宽松。在ARM Juno SoC[10]上,所有调试验证信号只能在安全状态下进行管理。因此,如果这些信号被禁用,则非安全内核永远不能使用调试功能来调试非安全处理器,即使内核已经在非安全内容中拥有高权限。我们认为这种限制方法过于严格,因为它在某种程度上限制了调试功能的合法使用。i.MX53 SoC[51]的设计,与ARM Juno SoC相反。调试验证信号被设计为限制外部调试器的使用,然而,i.MX53 SoC允许外部调试器启用验证信号。我们认为这种限制方法过于宽松,因为它为这些信号引入了潜在的攻击面。
NAILGUN攻击依赖于对调试寄存器的访问,而访问通常通过内存映射接口来实现。直观地说,限制访问这些寄存器将有助于提高平台的安全性。然而,我们认为这种限制应该在硬件层面而不是软件层面进行控制。如果限制是由运行在非安全模式下的软件(如操作系统)实现的,则具有内核权限的恶意软件可以轻松绕过它。如果限制是在安全模式(例如TEE)中实现的,那么由于两种模式之间的语义差距,它可能会引入显著的性能开销。相反,如果应用硬件辅助访问控制,则可以通过硬件陷阱或中断来保护对调试寄存器的访问。在向联发科负责披露的过程中,我们了解到他们拥有基于硬件的TrustZone边界划分技术,他们计划使用该技术来限制对调试寄存器的访问,以减轻报告的攻击。
根据SoC制造商发布的信号管理机制,我们建议OEM和云提供商默认禁用所有调试验证信号。此默认配置不仅有助于保护安全内容不受非安全状态的影响,还避免了非安全异常级别之间的权限升级。同时,他们应允许具有相应特权的应用程序启用这些信号,以进行合法的调试或维护,并且信号的使用应严格遵循SoC制造商设计的管理机制。通过这种设计,允许合法使用特权应用程序的调试功能,而禁止滥用非特权应用程序。此外,由于调试功能是通过CoreSight组件和调试寄存器来利用的,因此对CoreSight部件和调试寄存器的访问应用类似的限制也可以形成有效的防御。
在大多数平台中,调试寄存器作为I/O设备工作,攻击者需要手动将调试寄存器的物理地址映射到虚拟内存地址空间,这需要内核权限才能访问这些寄存器。在Linux内核中,使用内核权限执行代码的常规方法是加载LKM。传统PC环境中的LKM通常提供额外的驱动程序或服务。然而,在移动设备和物联网设备的场景中,在不太需要LKM的情况下,我们可以禁用LKM的加载,以防止任意代码执行在内核特权中。在这种情况下,即使攻击者通过SuperSU[37]等工具获得了root权限,也无法将调试寄存器映射到内存中。此外,为了防止攻击者用启用LKM的自定义内核替换库存内核,OEM可以添加一些额外的哈希/校验和来验证内核映像。请注意,禁止自定义内核并不一定会影响闪存自定义ROM,第三方ROM开发人员仍然可以基于库存内核开发他们的ROM。
在本文中,我们对ARM调试功能进行了全面的安全分析,并总结了其安全含义。为了更好地理解这个问题,我们还研究了一系列由不同SoC供电并部署在不同产品领域的基于ARM的平台。我们的分析和调查通过调试架构暴露了ARM设备的攻击面。为了进一步验证其含义,我们设计了一种名为NAILGUN的新型攻击,该攻击通过滥用调试功能,获得敏感信息,并在高特权模式和低特权模式下实现任意有效载荷执行。我们在具有不同ARM架构的真实设备上的实验表明,我们研究的所有平台都容易受到攻击。我们还讨论了ARM生态系统不同层对我们的攻击的潜在对策,以提高商业设备的安全性。