ARTICLE DETAIL

资讯详情

深耕商务建站与企业官网运营的一线实战洞察。

嵌入式系统安全实战:启动链、USB控制、证书与权限四层防护

嵌入式系统安全实战:启动链、USB控制、证书与权限四层防护 Embedded System Security Live看到这个标题先别急着把它翻译成“嵌入式系统安全现场直播”。做设备安全的人应该都有过这种体会真正让你头疼的不是买一套安全方案装上就完事而是设备在真实环境里跑着跑着突然有一天跟你闹脾气——启动验证挂了、USB设备被策略拦死、CA证书装不上、数据库视图又报权限错误。我在最近一次给开发板做安全加固时一天之内把这四类问题挨个遇了一遍从华硕主板开机直接进恢复界面到调试器插上电脑弹“当前安全策略已阻止此USB设备”再到给Android模拟器 push 证书被 read-only 拦下。这篇文章就顺着这四个现场讲把嵌入式系统安全最核心的四层问题——安全启动、运行时访问控制、证书信任链、权限模型——一次讲透。适合正在做嵌入式开发、物联网设备研发的工程师也适合刚转安全方向、想搞懂“设备安全到底在防什么”的读者。1. 嵌入式安全不是“装个锁”从一次真机调试说起1.1 安全事故的“迟到效应”做嵌入式系统安全的第一步是接受一个反直觉的事实大部分安全问题不会在你上线那天暴露。设备可能已经在产线上稳定跑了半年突然某天因为一次证书过期、一次OTA更新把信任库刷坏、或者某个安全Agent进程静默退出问题才真正浮出水面。这种“迟到效应”特别容易让人误判因为设备平时看起来一切正常你以为安全配置是生效的实际上它可能在你不知道的时候已经悄悄失效了。我在实际调试中越来越觉得“安全”不是一个静态快照不是一个“开启/关闭”的开关。Secure Boot 开着不代表信任链上的每个组件都被正确校验过USB策略配了不代表每个接口都按新策略执行证书装进系统了不代表上层应用真的走了系统信任库的校验。安全状态会漂移这是嵌入式设备运维里最隐蔽的风险也是我强调“Live”这个视角的原因——安全不是一个瞬间动作而是在设备持续运行过程中不断被验证、不断被维护的动态过程。1.2 一天之内的四次“安全翻车”现场为了把问题讲具体我直接复盘我那次调试过程。设备是一块跑Linux的开发板配套一台Windows宿主机外加一个Android模拟器做联动测试。一天之内我先后遇到四个故障宿主机开机直接进恢复界面提示“启动策略变更”Secure Boot 显示开启但进不了系统把调试器插到电脑上Windows 直接弹窗“当前安全策略已阻止此USB设备”想给 Android 模拟器装一个自签 CA 证书用于调试adb push 到/system/etc/security/cacerts时报 read-only导数据库视图时报了SQL SECURITY DEFINER相关错误显示definer账户不存在。这四个故障表面看毫不相关一个是 BIOS/UEFI 层一个是系统外设层一个是证书信任层一个是数据库权限层。但它们背后的逻辑是同一件事——信任与权限。设备是否允许这段代码运行、是否允许这个设备接入、是否允许这个证书通过、是否允许这个账户执行操作本质都是“你的身份是否被当前安全模型接受”。想通了这条主线排查思路一下就清晰了。1.3 一条主线启动链、运行时、证书、应用层权限顺着这条“信任与权限”的主线我把嵌入式系统安全分成了四个层次。设备上电后的第一件事是启动链校验由 BootROM、Bootloader、内核逐级验证签名这是整个信任体系的地基系统跑起来之后运行时访问控制接管 USB、外设、文件系统等资源的使用权限再往上设备与云端、设备与调试工具之间的通信依赖证书信任链来保证彼此身份可信最后应用和数据层的权限模型决定了一个进程、一个账户能对资源做什么操作。这四层不是孤立存在而是层层递进的。启动链一旦失守后面的所有安全机制都可以被绕过运行时访问控制如果配置错误会让合法调试工具也无法使用证书信任链如果断了设备会变成“谁也不信”或者“谁都信”两个极端权限模型如果设计混乱应用层就会出现各种“允许了但执行不了”“执行得了但权限过大”的怪问题。后面的内容我就按这四层逐个拆开讲。2. Secure Boot 与信任根为什么“开了安全启动”还是进不了系统2.1 华硕主板开机失败Secure Boot 的 Enabled 状态为什么不可信先说我那个最直接的教训。机器是一块华硕主板BIOS 里 Secure Boot Control 明明是 EnabledWindows 也装得好好的但某天早上开机直接进了恢复界面提示“启动策略变更系统无法正常启动”。当时第一反应是系统坏了后来才发现问题出在 Secure Boot 的信任库上。Secure Boot 的核心机制是用一组密钥和签名数据库来约束启动过程Platform KeyPK是所有权的根相当于你给大楼配的总钥匙Key Exchange KeyKEK负责管理签名数据库的更新相当于物业手里的钥匙串DB 是白名单记录允许启动的引导程序签名DBX 是黑名单记录已知恶意或已撤销的签名。计算机启动时固件会逐级验证引导程序签名是否在 DB 白名单里、是否不在 DBX 黑名单里校验通过才放行。而问题恰恰出在“数据库更新”环节。华硕主板把 Secure Boot 分成 Standard 和 Custom 两种模式Standard 模式由厂家维护默认密钥Custom 模式允许用户自定义 PK/KEK/DB。我虽然在 BIOS 里开着 Secure Boot但之前为了调试一个老系统把模式切到了 Custom并替换了 Platform Key。系统更新时Windows 会尝试更新 DB/DBX 数据库但在 Custom 模式下新数据库的更新请求需要用正确的 KEK 签名而我没有同步更新 KEK导致本地引导程序的签名不在当前信任列表里。最终结果是Secure Boot 状态显示 Enabled但信任链其实已经断裂系统自然进不去。组件作用类比PKPlatform Key所有权的根控制 KEK 的更新大楼总钥匙KEKKey Exchange Key管理签名数据库更新物业钥匙串DB允许启动的签名白名单员工门禁名单DBX禁止启动的签名黑名单黑名单通缉令这次事故让我彻底明白Secure Boot 的“Enabled”只是一个状态标志它只说明“这个功能在运行”不代表“信任链是完整的”。你换了 PK却没同步 KEK 和数据库系统照样进不去。很多嵌入式工程师遇到类似问题第一反应是关掉 Secure Boot 省事但这不是解决问题的办法正确做法是把密钥管理纳入系统更新的整体流程保证平台密钥、交换密钥、签名数据库三者始终同步。2.2 嵌入式设备里的引导验证U-Boot、TF-A 与 AVB 的实际链路PC 上的 Secure Boot 是 UEFI 那一套嵌入式设备则更复杂但也更贴近“从零构建信任链”。以我调试的这块开发板为例用的是常见的 ARM 启动流程BootROM 固化在芯片内部最先执行接着是 TF-ATrusted Firmware-A的 BL1、BL2、BL31负责初始化内存、加载 EL3 运行时环境再往后是 U-Boot作为主流引导加载程序加载内核和设备树如果运行 Android 或需要 AVBAndroid Verified Boot还会多一层 vbmeta 分区验证。每一步都需要校验下一级镜像的签名。BootROM 里烧录了根公钥BL1 的镜像签名由它验证BL2 加载 BL31 和 BL33U-Boot时用 bootchain 里的密钥做验签U-Boot 加载 kernel 时可以启用 verified boot 机制要求内核镜像和 DTB 必须是经过签名的 fitImage。这个链条只要有一个环节没有验签或者签名密钥被换掉后面的代码就可能被替换成恶意版本。我在实际配置 U-Boot 时最常踩的坑是CONFIG_CMD_AVB和CONFIG_ANDROID_AB这些宏没有正确组合导致 vbmeta 校验没有生效或者签名镜像和未签名镜像混用调试时把未签名的内核刷进去也启动了看起来“没问题”其实整个签名链已经失效。嵌入式设备不像 PC 有成熟的系统更新机制很多团队把 Secure Boot 开起来就不再管了结果几个月后要升级固件发现新镜像没有签名又要重新烧 Bootloader。2.3 密钥管理才是大头开发密钥、生产密钥与回滚保护把 Secure Boot 真正用起来的难点不是开启功能而是把密钥生命周期管理好。第一次做签名方案的工程师很容易陷入一个误区拿开发期间的测试密钥当生产密钥或者所有人共用一把签名私钥。这样的结果就是私钥泄露后没有任何补救手段因为一个密钥被用来签了所有的镜像撤销就等于整个系统重建。我建议从一开始就做密钥分离。至少分成两级平台密钥和应用密钥。平台密钥用于 BootROM 至 U-Boot 的基础链路应用密钥用于内核、设备树、文件系统等更上层的镜像。私钥存放在 HSM 或芯片的 OTP 区域里生产环境不要让它出现在开发机上开发机使用的测试密钥和生产密钥严格区分即使测试私钥泄露也不影响生产设备。回滚保护同样不能少RPMB 或 TPM NV 里维护一个回滚计数器每次升级把版本号递增旧版本镜像即使签名有效也会被拒绝加载防止攻击者把系统降级到存在已知漏洞的版本。实际踩坑后的体会是密钥管理和更新机制最好在设备量产前就定义清楚否则后面补会非常痛苦。比如有些团队在产品发出去一两年后才想加签名验证却发现还需要 OTA 升级 Bootloader而没有可信升级通道于是只能依赖产线返厂或现场刷机成本高得惊人。2.4 怎么确认安全启动真的在干活正面测试与负面测试调试完了 Secure Boot我最想分享的一点是不要只看状态位一定要做“正反两向测试”来确认签名验证真的在拦截。正面测试很简单用已签名的完整镜像执行一次正常启动观察启动日志中是否出现类似 “Verification passed” 或 “Signature OK” 的字段。每个 Bootloader 的日志位置不一样但基本都会在加载下一级镜像时打印验证结果。负面测试才是关键。把内核镜像里的一个字节改掉或者直接用未签名镜像重新打包然后尝试启动。如果 Secure Boot 生效启动流程必须被卡住报签名校验失败如果设备照样跑起来说明验证路径根本没接通。做过负面测试之后你会对自己的信任链有信心得多。很多年前我们调试一个新平台所有人以为签了名结果发现 BootROM 里的公钥哈希和实际密钥不匹配负面测试直接暴露了问题如果没做这一步设备到用户手里过几天就可能在某个更新后被刷成砖。3. 运行时访问控制USB设备被安全策略拦下的完整排查链路3.1 插上调试器就被拦“当前安全策略已阻止此USB设备”的现场调试器插上电脑第一时间不是滴一声然后出现在设备管理器里而是弹出一个“USB device has been blocked by the current security policy”的提示。设备管理器里翻半天也看不到新设备或者看到了也是黄色感叹号错误代码指向策略拦截。说实话第一次遇到这个问题我愣了一下因为这只调试器在另一台机器上插得好好的没有任何硬件故障迹象。这种拦截大多数时候并不是设备坏了而是当前操作系统或管理策略环境不允许这个 USB 设备接入。安全策略为什么要管 USB因为 USB 是物理攻击和数据泄露最常见的入口一个恶意 USB 设备可以被识别成键盘输入指令一个 U 盘可以把内部资料拷走。为了控制风险系统从设备安装、存储访问、设备类型等好几个层面都设置了检查点任何一个不满足设备就会被拦在门外。3.2 三层拦截机制设备安装策略、USB存储隔离与设备自身策略我排查时会把 USB 被拦的问题分成三个层次来定位。第一层是 Windows 的设备安装限制Device Installation Restrictions。这是企业 IT 最常用的策略通过组策略或 MDM 统一下发可以精确控制允许安装的硬件 ID、设备类或设备实例路径。如果你插入的调试器不在允许列表里或者策略配置成“阻止安装其他策略未描述的设备”那么系统直接拒绝安装驱动设备自然无法工作。第二层是 USB 存储隔离。很多公司的安全策略会限制可移动存储设备例如禁止写入 U 盘、禁止挂载未知设备。这个策略的目的当然是防数据泄露但它经常误伤调试器、TAP 设备、串口转换器这类虽然长得像外设但不是存储设备的东西。还有一个隐蔽点某些策略会检查设备的接口类型如果你的调试器恰好实现了大容量存储接口可能被当成 U 盘处理。第三层是设备自身的安全设置。嵌入式设备或 Android 设备往往有自己的访问控制例如 Android 的 USB 调试需要开发者选项确认指纹某些锁定 Bootloader 的设备还会校验 USB 连接是否来自可信主机。在一些军工、电力等对安全要求很高的场景设备会直接限制 USB 配置接口任何未授权的 USB 操作都会被拒绝。热搜词里那个 “this action is not allowed with this security level configuration” 的提示我在设备端也遇到过意思就是当前安全级别不允许这个操作通常需要先提升权限或切换安全配置文件。3.3 完整排查链路从事件日志到组策略结果集遇到 USB 被拦不要急着改策略先按下面的链路排查。第一步确认拦截发生在主机侧还是设备侧。最简单的办法是把同一个设备换到一台没有任何管控策略的干净电脑上试一次。如果干电脑能正常识别问题基本在主机侧如果干电脑也报错那更可能是设备自身的问题。第二步如果是主机侧问题在 Windows 上查看组策略结果集。运行gpresult /h report.html生成 HTML 报告后搜索“设备安装”相关策略重点看是否启用了“设备安装限制”或“阻止其他策略未描述的设备”。有时候策略来自本地组策略有时候来自域或 MDM 平台来源不同处理方式也不同。第三步打开事件查看器定位到设备安装相关日志。Windows 在阻止设备安装时会记录设备安装事件里面包含被阻止设备的硬件 ID 和拦截理由。拿到硬件 ID 之后去设备安装限制策略里比对确认这个设备是否在白名单范围。第四步制定最小化放行方案。如果被拦的是合法调试工具可以精确放行该设备的硬件 ID 或者设备实例路径而不是把整个设备安装限制关掉。举个例子如果策略阻止了“其他设备”你可以单独添加一条允许规则用VID_xxxxPID_yyyy指定这只调试器。我见过有人图省事直接把“设备安装限制”策略停用结果一个同事把私人的 USB 摄像头带进公司第二天安全部门就找上门了。正确的做法永远是开一个“只允许特定设备”的窗口而不是把整面墙拆掉。3.4 文件安全权限的姊妹坑“could not set file security for file”与“wrong security type”同样属于运行时访问控制的还有一个高频问题就是往设备复制文件或给服务安装目录设置权限时报 “could not set file security for file”。我第一次遇到这个报错是在给一块开发板的 FAT 分区写配置时Windows 报无法设置文件安全属性。查了一圈发现FAT32/exFAT 这类文件系统根本上不支持 Windows 的 ACL 安全描述符系统想往文件上写权限规则文件系统根本不认。NTFS 下用得好好的 ACL到 FAT 分区上就成了“无效安全类型”。这个报错和“wrong security type”是姊妹问题。简单来说安全类型不匹配指你尝试应用的安全主体在目标系统上无法被识别。好比你把一串印着某个制服标识的钥匙带到另一个大门口门禁系统里根本没有这个标识的登记信息它自然不知道该怎么处理你的权限申请。排查思路很直接先看目标文件系统支不支持 ACL再看目标系统里是否存在当前 SID 或用户名的映射。嵌入式设备上尤其常见因为很多设备分区采用非 NTFS 格式或者使用独立的用户体系和 Windows 的 SID 完全映射不上。解决方案分几种如果只是为了在宿主机和设备之间传文件把目标分区换成支持 ACL 的文件系统或者干脆通过 adb/scp 等工具传文件不走 Windows 文件共享如果必须在设备上设置权限要使用设备自身的用户体系和权限命令而不是在宿主机侧设置安全属性。嵌入式设备上很多权限管理必须“到现场做”跨系统的安全描述符千成不能直接搬。4. 证书信任链装个CA证书怎么就撞上了read-only文件系统4.1 用 adb 装证书被 read-only 挡下的那一刻调试设备 HTTPS 流量时最常用的操作是给测试设备装一个自签 CA 证书让设备信任代理服务器的证书这样才能抓到加密包内容。我那次在 Android 模拟器上执行adb push my-ca.crt /system/etc/security/cacerts/结果直接报 “remote couldnt create file: read-only”也就是热搜里那条mumu adb /system/etc/security/cacerts remote couldnt create file: read-only的完整场景。第一反应是权限不够于是adb root再试一次还是 read-only。这时候才反应过来问题不是权限而是这个分区本身就是只读挂载。Android 系统证书目录在/system/etc/security/cacerts/system分区在生产镜像里默认以只读方式挂载这不是为了防止你装证书而是为了保护系统完整性。如果任何进程都能往系统目录里写文件那恶意软件也能把自己的恶意 CA 证书塞进去之后所有 TLS 流量都能被它劫持。所以系统镜像的只读属性本身就是一条安全边界。4.2 Android 证书存储机制的两次收紧从用户证书到 APEX很多老工程师习惯用老办法先拿到 root然后 remount 系统分区把证书 push 进去重启生效。这套流程在 Android 9 之前还行得通但 Android 系统的证书存储机制已经收得非常紧。用户证书和系统证书是两回事。通过设置里的“安装证书”装进去的证书属于用户证书存储只能被一部分应用信任很多应用为了安全默认不信任用户 CA。系统证书存储位于/system/etc/security/cacerts全系统进程都信任所以抓包工具都希望把证书装到这里。Android 14 之后系统 CA 证书被进一步收进了com.android.conscrypt这个 APEXAndroid Package EXtension模块。APEX 本身是一个只读的、经过签名的系统组件包即使你adb root后 remount 成功看到的/system/etc/security/cacerts也是一个由 APEX 管理、运行时可重置的内容直接往里写文件并不能稳定生效。在模拟器上调试比较可靠的做法是启动时加-writable-system参数让模拟器以可写系统模式运行再配合adb root和adb remount来修改证书目录。在自有测试设备上最简单且合法的路径是把证书安装为“用户证书”然后在应用的网络安全配置里手动信任该用户证书。虽然不如系统证书彻底但已验证场景足够用。需要强调的是以上操作只适用于开发者自有测试设备生产环境中的设备证书必须通过工厂预置或正式的 OTA 更新机制绝不能在运行现场用 root 硬塞证书那会彻底破坏设备的信任体系。4.3 设备端与云端信任验证别在两端偷懒证书信任链的问题不只出现在“往设备里装证书”这一步。设备作为客户端去访问云端时同样需要校验服务端证书。我在不少项目里看到过这样的代码为了省事把 TLS 证书校验直接关掉或者设置一个“信任所有证书”的 SSLContext。开发阶段这么干可以理解但如果带着这个开关上生产等于让设备裸奔——中间人轻轻松松就能把设备到云端的流量截走改指令、换固件、盗数据为所欲为。设备端校验证书我建议要么走系统 CA 库让设备信任常见 CA 链同时一定要校验主机名hostname防止证书链虽然有效但签给了另一个域名要么对特定的服务端证书做固定公钥校验pinning把预期公钥直接内置到固件里。前者维护成本低但依赖 CA 体系的安全后者对公共服务器的证书轮换比较敏感需要提前设计好证书更新方案。两种方式都要配套时间同步因为证书有效期验证依赖设备当前时间很多设备 RTC 电池没电或者从未做过 NTP 同步结果证书明明没过期设备却一直报“证书无效”。4.4 证书排查三步法设备信任库、应用加载路径、时间同步证书类问题排查我总结了一个三层检查法
返回列表
PREV
查看更多资讯
NEXT
返回资讯列表