1. 项目概述:当硬件安全遇上飞行安全
最近在折腾无人机飞控安全测试,一个挺有意思但细思极恐的切入点进入了我的视野:电压毛刺故障注入攻击。简单说,就是通过人为制造电源上的瞬间电压波动(毛刺),去干扰甚至“欺骗”飞控芯片,让它执行错误的指令或者直接“死机”。这听起来像是电影里的黑客桥段,但在实验室环境下,它已经是一种被验证的、针对嵌入式系统(尤其是像PX4、ArduPilot这类开源飞控)的有效攻击手段。我之所以花时间深挖这个主题,是因为它触及了无人机安全最底层、也最脆弱的一环——硬件与固件交互的可靠性。我们平时讨论无人机安全,大多聚焦在通信链路加密、地面站软件漏洞或者GPS欺骗上,却很少关注到,一块小小的开发板,其供电系统的纯净度可能就是整个系统的“阿喀琉斯之踵”。
PX4作为全球最流行的开源飞控软件之一,被广泛应用于科研、教育和工业无人机领域。它的魅力在于开源、可定制,但硬币的另一面是,其硬件参考设计(如Pixhawk系列)和软件失效保护机制,在面对精心设计的硬件级攻击时,可能暴露出意想不到的漏洞。这次,我就想结合自己的测试和代码分析,拆解一下电压毛刺攻击的原理,并深入PX4的失效保护(Failsafe)机制,看看在极端异常供电情况下,这些保护逻辑是否真的能如我们所愿地接管系统、安全降落。无论你是无人机开发者、安全研究员,还是资深发烧友,理解这些底层风险,对于设计更鲁棒的无人机系统或评估现有产品的安全性都至关重要。
2. 电压毛刺故障注入攻击原理深度拆解
2.1 什么是电压毛刺?它从何而来?
电压毛刺,英文常称作Voltage Glitch或Power Glitch,指的是电源电压在极短时间内(通常是纳秒到微秒级)发生的非预期的、剧烈的波动。这种波动可能表现为一个瞬间的电压凹陷(Drop)或尖峰(Spike)。在理想的电路中,我们期望供电电压是一条平滑的直线(比如5.0V或3.3V),但现实世界中,它充满了“噪音”。
毛刺的来源非常广泛:
- 内部因素:芯片内部逻辑门开关时的电流突变、时钟信号边沿的反射、不同电路模块之间的串扰。
- 外部因素:电机(特别是无人机无刷电机)启停时产生的反电动势、舵机突然加载、电源模块(如BEC)负载瞬变、甚至外部电磁干扰。
在故障注入攻击的语境下,我们关注的是人为制造的、具有特定时序和幅度的毛刺。攻击者使用专门的设备(如Glitch Generator),在精确计算的时刻,向飞控处理器的电源引脚注入一个短暂的电压异常。这个“精确的时刻”往往是攻击成败的关键,通常瞄准处理器执行特定安全校验代码、访问关键内存(如存储着解锁密码或飞行模式的区域)或进行条件跳转判断的时钟周期。
2.2 毛刺如何导致芯片“行为错乱”?
要理解攻击原理,我们需要一点数字电路和微处理器架构的基础知识。现代飞控主控(如STM32系列ARM Cortex-M)的核心是数百万甚至上亿个晶体管。它们的工作状态(开或关)由电压阈值决定。当时钟信号到来,这些晶体管根据输入的电平变化,进行逻辑运算和数据传输。
电压毛刺攻击主要利用了两个半导体物理效应:
时序违例(Timing Violation):芯片内部数据从寄存器A传到寄存器B需要一定时间(建立时间和保持时间)。如果供电电压突然降低,晶体管的开关速度会变慢,导致信号传播延迟增加。一个原本能在时钟周期内稳定传输的数据,可能因为这次“减速”而无法准时到达,从而被错误地锁存。从软件角度看,这可能导致一个变量的值从
0xAA莫名其妙变成了0x55,或者一条条件判断指令if (system_armed == false)因为system_armed这个变量在读取瞬间被毛刺破坏,而被误判为true。指令抓取/解码错误(Instruction Fetch/Decode Error):处理器从Flash中读取指令代码也是一系列的电平信号。一个发生在指令读取总线上的电压毛刺,可能翻转某一位数据。例如,将加法指令
ADD的操作码(一串特定的二进制数)的某一位从0变成1,可能就变成了跳转指令JMP。处理器就会错误地跳转到攻击者期望的地址去执行代码。
注意:这种攻击不依赖于软件漏洞,它攻击的是硬件在非正常工况下的物理特性。因此,即使飞控固件没有任何缓冲区溢出或逻辑漏洞,也可能中招。
2.3 攻击场景与设备简析
在无人机场景下,实施此类攻击的典型路径是接近无人机的电源系统。例如,攻击者可能制作一个伪装成普通电源滤波器的夹持设备,串联在飞控的供电线上(通常是5V或3.3V线)。更隐蔽的方式是利用无人机自身的电机驱动电路产生的噪声,通过耦合等方式影响飞控核心供电。
用于生成毛刺的设备从简单到复杂:
- 简单方案:一个高速MOSFET开关电路,配合精密的延时触发器,就能产生一个可控的电压跌落。
- 专业设备:如ChipWhisperer、Riscure Glitcher等,它们能提供纳秒级的时间精度、可编程的毛刺形状(宽度、幅度),并与目标设备的时钟同步,实现“指哪打哪”的精准注入。
攻击的目标通常是飞控的安全临界操作,例如:
- 绕过解锁(Arming)校验:在检查遥控器信号、GPS定位是否安全的代码段注入毛刺,使检查条件意外通过,实现“远程强制解锁”。
- 篡改失效保护触发逻辑:当遥控器信号丢失时,PX4会触发Return-to-Launch(RTL)或Land(降落)模式。攻击者可能在触发判断的瞬间注入毛刺,使系统误认为信号已恢复,或错误地选择了一个危险的失效保护动作(如继续悬停直至电量耗尽)。
- 导致看门狗(Watchdog)失效:看门狗是系统最后的“救命稻草”,如果定期喂狗的程序段被毛刺干扰而错过喂狗,或者看门狗电路本身因毛刺复位,会导致系统非预期重启,在飞行中这是灾难性的。
3. PX4失效保护机制架构与工作流程
3.1 PX4安全架构概览
PX4设计了一套多层次、可配置的失效保护系统,其核心思想是状态监控与分级响应。它不是单一的功能,而是一个分布在多个模块和线程中的协同体系。主要监控的对象包括:
- 遥控器输入(RC Loss)
- 数据链路(Data Link Loss,用于自主飞行)
- GPS定位(GPS Loss)
- 电池电量(Battery Low/Critical)
- 传感器健康度(Sensor Failure,如加速度计、陀螺仪)
- 外部系统状态(如规避系统、任务计算机)
这些监控器持续运行,一旦检测到异常,就会向失效保护状态机报告一个“要求动作”。这个状态机位于Navigator模块中,是决策中枢。
3.2 失效保护状态机决策逻辑
失效保护状态机(Failsafe类)的工作流程可以简化如下:
- 状态检测:各个订阅者(如
RCUpdate模块检查遥控器信号,VehicleGlobalPosition模块检查GPS)定期发布其健康状态。 - 动作请求:每个失效保护条件都配置了触发阈值(如遥控信号丢失超过1秒)和对应的建议动作。动作有优先级,通常遵循:降落(Land) > 返航(RTL) > 保持(Hold) > 警告(Warning) > 无。
- 仲裁与决策:状态机收集所有激活的失效保护动作请求,根据预定义的优先级(可在参数中配置,例如
NAV_RCL_ACT,NAV_DLL_ACT等)选择一个最终要执行的动作。这里有一个关键点:用户可以通过遥控器开关或地面站指令,临时覆盖或禁用某些失效保护。 - 动作执行:决策结果会传递给
Commander模块,由它来改变飞行模式(如从Position模式切换到Land模式),并由Flight Task和Controller执行具体的控制指令。
3.3 关键代码路径与参数分析
让我们深入到代码层面,看两个关键点:
遥控器丢失检测 (src/modules/rc_update/RCUpdate.cpp):
// 简化后的逻辑 if (last_valid_signal_timestamp + RC_LOSS_TIMEOUT_MS < current_time) { // 信号超时,触发失效保护 _failsafe_flags.rc_loss = true; // 发布状态更新... }这里的RC_LOSS_TIMEOUT_MS是一个关键参数。攻击者如果能在每次超时前瞬间“修复”信号(通过毛刺干扰判断逻辑),就能让系统永远检测不到信号丢失。
失效保护仲裁 (src/modules/navigator/Failsafe.cpp):
// 在 update() 函数中 int selected_action = ACTION_NONE; for (每个激活的 failsafe) { if (该failsafe要求的动作优先级 > selected_action的优先级) { selected_action = 该failsafe要求的动作; } } // 检查用户是否手动覆盖 if (用户通过RC开关选择了“保持”模式 && selected_action是RTL或Land) { selected_action = ACTION_HOLD; }这里的漏洞窗口在于:从检测到异常,到仲裁完成,再到Commander执行模式切换,存在一个非零的时间窗口。在这个窗口内,系统状态可能是不一致的。更危险的是“用户覆盖”逻辑,它本意是提供灵活性,但如果覆盖指令的接收和处理过程被干扰,可能导致系统执行一个与当前危险状况不匹配的动作。
4. 漏洞场景:毛刺攻击与失效保护机制的对抗
4.1 攻击面分析
结合PX4的架构,电压毛刺攻击可能针对以下几个软硬件结合点:
传感器数据采集与滤波链路:ADC(模数转换器)在采样瞬间对电源噪声极其敏感。一个毛刺可能导致陀螺仪或加速度计读出一个巨大的、瞬时的错误值。虽然PX4有软件滤波(如卡尔曼滤波),但一个足够大且恰好在滤波窗口内的野值,仍可能被部分采纳,导致估算器(Estimator)认为无人机发生了剧烈姿态变化,从而触发姿态失控保护或直接输出错误的控制指令。
看门狗定时器电路:独立的硬件看门狗(如STM32的IWDG)通常由独立的内部RC振荡器驱动,相对抗干扰能力强。但有些设计为了节省成本,可能使用软件看门狗或配置不当的硬件看门狗。如果毛刺导致主晶振停振或时钟紊乱,可能直接影响看门狗的计时基准,或者干扰喂狗指令的执行,造成意外复位。
内存与Flash访问:失效保护的条件阈值、用户覆盖的标志位等都存储在内存中。毛刺可能导致:
- SRAM位翻转:将
failsafe_action变量从ACTION_LAND(降落)翻转为ACTION_NONE(无动作)。 - Flash读取错误:从参数存储区读取
NAV_RCL_ACT参数时发生错误,返回一个默认值或错误值,改变了失效保护行为。
- SRAM位翻转:将
中断与调度时序:PX4基于NuttX实时操作系统,依赖精确的定时中断。电压毛刺可能引起:
- 中断丢失:负责检测遥控器信号的定时中断服务程序(ISR)被跳过,导致连续多次检测不到信号,即使物理信号是存在的。
- 任务调度紊乱:高优先级的
Failsafe决策任务被延迟,而低优先级的任务(如日志记录)继续运行,使得系统响应危险状况的速度变慢。
4.2 一个假设的漏洞利用链
让我们构建一个具体的攻击场景,展示漏洞如何串联:
- 攻击准备:攻击者将一个小型毛刺发生器物理接入目标无人机的飞控5V供电线。
- 触发条件:无人机正常飞行,遥控器信号稳定。攻击者等待或主动制造一个条件(如让无人机飞至遥控器边缘,信号变弱但不完全丢失)。
- 首次注入:在
RCUpdate模块即将进行“信号是否超时”判断的前一个时钟周期,注入一个负向电压毛刺。目标:使从IO口读取遥控器PWM值的操作发生错误,读出一个“有效”但实际是伪造的值。这可能导致last_valid_signal_timestamp被错误更新,重置了超时计数器。结果:遥控器丢失失效保护被无限期抑制。 - 二次注入:此时,无人机可能因其他原因(如GPS丢失)进入了RTL模式。攻击者监听飞控与数传电台的通信(或根据时间估算),在
Navigator的失效保护状态机执行“用户覆盖检查”的代码段时,进行第二次毛刺注入。目标:篡改存储“用户当前选择的模式”的变量,使其从“无覆盖”变为“保持(Hold)模式覆盖”。结果:失效保护状态机仲裁后,本应执行RTL,但因“检测到”用户覆盖,最终指令变为保持悬停。 - 最终后果:无人机在遥控器实际已失效、GPS可能也不良的情况下,悬停在半空,直至电池耗尽坠毁。
这个链条的关键在于对代码执行流和内存状态的精确“计时攻击”。它不需要破解加密算法,而是利用了硬件在异常条件下的非确定性行为。
4.3 实际测试中的观察与挑战
在受控的实验室环境下(使用开发板而非真实飞行),通过ChipWhisperer平台进行电压毛刺测试,我观察到一些现象:
- 重复性难题:同样的毛刺参数(幅度、宽度、注入点),并非每次都能成功。这与芯片的制造工艺偏差、环境温度、甚至当时芯片内部的具体操作有关。攻击更像是一种“概率游戏”,需要大量尝试来找到稳定的“攻击点”。
- 系统级影响难以隔离:一次成功的毛刺注入,可能导致整个系统崩溃、重启,而不仅仅是预期的位翻转。这使得针对特定功能(如只绕过解锁而不影响其他功能)的攻击非常困难。
- 现代芯片的增强防护:较新的STM32系列(如H7系列)具有更强的电源监控、内存保护单元和时钟安全系统,使得毛刺攻击的门槛大大提高。
5. 防御策略与加固建议
面对这种底层硬件攻击,没有银弹,但可以通过“防御纵深”策略层层设防,显著提高攻击成本和难度。
5.1 硬件层加固
这是最根本也是最重要的一环。
- 电源完整性设计:
- 在飞控处理器和所有关键传感器(IMU, 气压计)的电源引脚就近部署大容量(10uF)钽电容和小容量(0.1uF)陶瓷电容组成的去耦网络,用于滤除不同频率的噪声。
- 使用低压差线性稳压器而非开关稳压器为核心芯片供电,因为LDO的噪声更低。如果必须使用DCDC,要选择高频、低噪声型号,并搭配优质的π型滤波电路。
- 对电源线进行物理隔离和屏蔽,特别是要远离电机驱动线、舵机线等大电流、高噪声线路。
- 时钟与复位电路:
- 使用带有展频技术(Spread Spectrum)的晶振,可以降低时钟边沿的电磁辐射,同时增加毛刺同步的难度。
- 配置并启用独立看门狗,且其时钟源应尽可能独立于主时钟(如使用内部LSI)。确保看门狗的超时时间设置合理,既不能太短(容易被正常操作干扰),也不能太长(失去及时复位的能力)。
- PCB布局与布线:
- 遵循严格的模拟/数字地分割,并在单点连接。
- 关键信号线(如时钟、复位、烧录接口)尽量短,并做包地处理。
5.2 固件/软件层加固
在硬件基础上,软件可以增加检测和恢复机制。
- 冗余与一致性校验:
- 关键变量冗余存储:对于像
failsafe_action、arming_state这样的关键状态变量,可以在内存中存储三份,采用“三取二”或更复杂的投票机制进行读取。 - 定期自检:在空闲任务或低优先级任务中,定期对关键数据结构和代码段进行CRC校验,确保其未被意外修改。
- 关键变量冗余存储:对于像
- 失效保护逻辑增强:
- 引入“粘滞”状态:一旦某个失效保护被触发,即使条件瞬间恢复,也应保持该保护状态至少数秒钟,并需要更严格的条件(如持续稳定的信号)才能解除。这可以抵御间歇性的毛刺干扰。
- 超时链与升级机制:例如,遥控器丢失触发RTL,RTL过程中如果GPS也丢失,则不应再回退到悬停,而应直接升级为降落。避免因多条件被逐个干扰而退化到不安全状态。
- 最小化“用户覆盖”权限:在高风险失效保护(如电池严重不足、姿态严重失控)时,应完全禁止用户通过遥控器覆盖,只能通过地面站进行高级别恢复操作。
- 异常行为检测:
- 监控系统任务的执行周期。如果
Failsafe决策任务的执行间隔异常拉长,这本身就可以作为一个高级别的失效保护触发条件。 - 对比不同传感器(如光流与GPS)计算出的速度/位置,如果出现不可解释的巨大差异,可能预示着某个传感器链路受到了干扰。
- 监控系统任务的执行周期。如果
5.3 系统级与操作规范
- 飞控选型:在安全苛求的应用中,考虑使用具有锁步内核或内置硬件安全模块的处理器。锁步内核是两个完全相同的核心执行相同的代码并比较输出,任何不一致都会触发错误,能有效防御瞬态故障。
- 环境感知与规避:对于恶意攻击,物理接近通常是前提。无人机可以配备简单的射频环境监测传感器,当检测到异常强度的、特定频率的干扰源靠近时,主动触发最高级别的保护(立即降落并报警)。
- 开发者与用户教育:让开发者了解硬件安全威胁,在设计和代码审查时考虑这些边缘情况。让用户明白,开源飞控的强大伴随着自我负责的风险,不应在未经安全评估的关键任务中使用。
6. 总结与个人实践心得
电压毛刺攻击揭示了无人机安全中一个常被忽视的维度:硬件可靠性与软件安全性的交界地带。PX4等开源飞控在功能性和灵活性上取得了巨大成功,但其诞生于相对友好的研发环境,默认的硬件设计和软件机制对恶意硬件攻击的考量不足。这项研究的目的不是制造恐慌,而是为了促进更健壮的设计。
在我自己的实验和代码审计过程中,最大的体会是:安全是一个系统性问题。你不能只加固一扇门而忽略窗户。对于个人开发者或小型团队,从硬件设计之初就重视电源完整性,在软件中为关键状态增加冗余和合理性检查,这些成本可控的措施能极大提升系统的抗干扰能力。同时,作为用户,理解你所使用的系统的局限性至关重要。在电磁环境复杂的区域(如高压线附近、大型无线电发射站旁)飞行,或者进行超视距作业时,要意识到这些超出常规测试场景的风险。
最后,开源社区的力量在于透明和协作。通过公开讨论这类深层漏洞,吸引更多硬件安全专家和嵌入式开发者的关注,共同审查代码、提出改进方案,才能让像PX4这样的优秀项目在安全性的道路上走得更远、更稳。毕竟,无人机的天空,不仅需要自由翱翔的代码,更需要坚如磐石的守护。