引言
物联网安全的特殊性在于攻击面横跨三个世界:几块钱的 MCU、跑着 Linux 的网关、以及承载百万连接的云平台。任何一个环节失守,攻击者都能顺着设备到云的信任链横移。2016 年的 Mirai 僵尸网络用 61 个默认口令感染了约 60 万台摄像头与路由器,打出了 620 Gbps 的 DDoS,直接拖垮了 Krebs on Security 与 Dyn DNS,这不是精巧的漏洞利用,而是把「出厂默认口令 + 暴露的 Telnet 端口」扫了一遍。
设备侧的约束又极其苛刻:算力以 MHz 计、内存以 KB 计、电池要撑十年、BOM 成本按分钱抠,而且一旦部署到现场,往往几年都摸不到。这意味着很多在服务器上理所当然的安全手段(常驻杀毒、在线补丁、强口令轮换)在设备上根本跑不起来,必须换成硬件信任根、一次性熔断、证书身份这类「出厂即固化」的方案。
更麻烦的是生命周期错配:设备硬件寿命 10 年,云平台 API 三年一换,TLS 库的 CVE 平均每周新增几十个。你不能指望十年后还能远程升级一台装在井盖下的水表。因此安全设计必须假设「部分设备永远无法更新」,把防线前移到制造与入网阶段。
本文按「威胁模型 → 身份密钥 → 传输安全 → 安全启动 → 固件加固 → 平台加固 → 合规 → 漏洞响应」的顺序展开,最后给出可直接套用的加固配置示例与常见坑清单。设备侧与云侧的对接细节,可配合 MQTT 协议与主题设计 与 OTA 固件升级 一起阅读。
目录
- 威胁模型与真实事件
- OWASP IoT Top 10 与 STRIDE 映射
- 身份与密钥体系
- 传输安全:TLS、mTLS 与 DTLS
- 安全启动与信任根
- 固件与调试口加固
- 网络与平台侧加固
- 隐私与合规
- 漏洞响应与安全更新
- 加固配置示例
- 安全测试与验证
- 纵深防御与安全运营
- 权衡取舍
- 常见坑清单
- 小结
1. 威胁模型与真实事件
做安全加固的第一步不是买安全芯片,而是写清楚威胁模型:谁想攻击、图什么、从哪个口进来。设备侧的典型威胁分四类。
- 远程入侵:默认口令、弱口令、未授权暴露的 Telnet/SSH/HTTP 管理口。Mirai、BrickerBot、Satori 都走这条路。
- 固件攻击:通过 UART/JTAG 读出 Flash,逆向出密钥、算法与业务逻辑,或直接改固件刷回。2020 年多个智能门锁被曝出可用 SPI 夹子读密钥。
- 供应链与制造环节:代工厂多烧一批固件、密钥未做一机一密导致全局密钥泄露、测试固件流入量产。
- 平台侧:越权订阅他人 Topic、重放旧指令、伪造设备上报、拖库。
把这些落到 STRIDE 上,就是 Spoofing(伪造设备身份)、Tampering(篡改固件与报文)、Repudiation(否认上报)、Information Disclosure(密钥与隐私泄露)、Denial of Service(耗尽连接与带宽)、Elevation of Privilege(越权控制其他设备)。
几个标志性事件值得记住,它们几乎定义了 IoT 安全的「基本功」清单:
| 事件 | 年份 | 攻击面 | 教训 |
|---|---|---|---|
| Mirai | 2016 | 默认口令 + 暴露 Telnet | 出厂凭据必须唯一 |
| BrickerBot | 2017 | 弱口令 SSH/Telnet | 攻击者可以只破坏不勒索 |
| VPNFilter | 2018 | 路由器固件持久化 | 固件完整性校验不可省 |
| 智能门锁密钥提取 | 2020 | SPI 直读 Flash | 密钥必须进安全边界 |
| 摄像头越权直播 | 2021 | 平台 Token 权限过宽 | 设备级最小权限授权 |
这些事件的共同点是:攻击者并没有用零日漏洞,用的都是「设计阶段就该堵住」的配置问题。
2. OWASP IoT Top 10 与 STRIDE 映射
OWASP IoT Top 10 是一份很好用的自查清单,它把设备侧与平台侧的问题混排。工程上更实用的做法是把它映射到 STRIDE 与具体缓解手段,形成可执行的加固项。
| OWASP 条目 | STRIDE 归类 | 设备侧缓解 |
|---|---|---|
| 弱口令与可猜口令 | Spoofing | 出厂随机一机一密,禁止默认口令 |
| 不安全的网络服务 | Elevation | 关闭 Telnet,管理口仅限本地或跳板 |
| 不安全的生态接口 | Tampering | 云 API 鉴权、输入校验、限流 |
| 缺乏安全更新机制 | Tampering | 签名固件、A/B 分区、防回滚 |
| 使用过时组件 | Tampering | SBOM、CVE 扫描、依赖锁定 |
| 隐私保护不足 | Info Disclosure | 数据最小化、本地脱敏、加密存储 |
| 不安全的数据传输与存储 | Info Disclosure | TLS 1.3、Flash 加密、NVS 加密 |
| 缺乏设备管理 | Elevation | 设备生命周期、吊销、资产盘点 |
| 不安全的默认配置 | Elevation | 首启动强制改密、最小服务集 |
| 缺乏物理加固 | Tampering | 熔断调试口、读保护、防拆开关 |
映射的意义在于:每一条都对应一个可验收的加固动作,而不是一句「注意安全」。
3. 身份与密钥体系
设备身份是整个信任链的起点。主流方案有三档。
- 一机一密(对称):每台设备出厂烧入唯一 ID 与唯一密钥(如 32 字节),服务端存对应关系。实现简单、算力开销低,但服务端一旦泄露全库密钥,等于全部设备沦陷,且无法防抵赖。
- 一机一证(非对称):每台设备持有唯一私钥与 X.509 证书,用 mTLS 双向认证。服务端只存 CA 与吊销列表,泄露风险小,支持吊销。代价是握手开销大、证书管理复杂。
- PSK(预共享密钥):DTLS-PSK 或 TLS-PSK,适合极低算力设备,但同样有全局泄露风险,且难做细粒度吊销。
密钥存在哪里是关键。软件 Flash 里的私钥可以被读出,因此高安全等级设备必须把密钥放进安全边界:
| 方案 | 典型器件 | 能力 |
|---|---|---|
| 安全元件 SE | Microchip ATECC608A、NXP SE050、国密 SE | 私钥不可导出,芯片内完成签名/ECDH |
| TPM 2.0 | 网关与工控机 | 度量启动、密钥层级、密封存储 |
| eFuse / OTP | MCU 内置 | 一次性烧写密钥摘要或加密密钥 |
| NVS 加密 | ESP32 等 | 用 Flash 加密密钥保护 NVS 分区 |
以 ATECC608A 为例,私钥在出厂或首次上电时于芯片内生成,永不离开;设备申请证书时,由芯片对 CSR 签名,私钥只参与运算不参与导出。ESP32 的 NVS 加密配合 Flash 加密,可以把 WiFi 口令、云平台 token 从明文存储中移出。设备身份与云端设备模型、影子状态的绑定方式,参见 设备影子与状态管理 。
证书签发与轮换流程
一次典型的设备证书生命周期如下:
- 产线或首次上电:SE 内生成密钥对,导出公钥。
- 设备用私钥对 CSR(证书签名请求)签名,上报给注册服务。
- 注册服务校验设备身份(产线白名单、注册码、首次注册凭证)。
- CA 签发设备证书,设备存入安全存储。
- 运行时 mTLS 握手,服务端校验证书链与吊销状态。
- 到期前自动续签,旧证书进入过期缓冲期。
轮换策略上,90 天短证书配合自动续签比一年长证书更安全:泄露窗口小,吊销压力也小。但要注意设备时钟可能不准,证书校验要容忍一定时钟漂移,或改用服务器时间。
4. 传输安全:TLS、mTLS 与 DTLS
传输层的最低要求是 TLS 1.3(或 1.2 的受限套件)。TLS 1.3 砍掉了 RSA 密钥交换与一堆弱套件,握手从 2-RTT 降到 1-RTT,还支持 0-RTT 会话恢复,对弱网设备很友好。
- 密码套件:优先 TLS_AES_128_GCM_SHA256 与 TLS_AES_256_GCM_SHA384,禁用 CBC 与静态 RSA。
- 证书校验:设备必须校验服务端证书链与主机名,把 CA 固定(certificate pinning)在固件里,防止中间人。
- mTLS:设备与服务端互验证书,替代用户名口令,天然抗重放。
- 会话恢复:MQTT 长连接场景用 session ticket,减少重连握手开销。
一个常见误区是把「用了 TLS」等同于「传输安全」。如果设备侧禁用了证书校验,或者把 CA 放在可写分区里,攻击者一次中间人就能解密全部流量。设备端的 TLS 配置应显式声明最低版本与允许的套件,例如 mbedTLS 中限制为 TLS 1.2 以上并禁用弱套件,同时开启 MBEDTLS_SSL_VERIFY_REQUIRED 强制校验对端证书。
UDP 场景(CoAP、LwM2M)用 DTLS 1.2/1.3。DTLS 的重传与分片在丢包网络下表现一般,因此 OSCORE(RFC 8613)成为更轻量的选择:它在 CoAP 层做端到端加密,代理网关可以转发但读不到内容,适合 NB-IoT 这类低带宽链路。
证书轮换与吊销是长期运营的痛点。CRL 文件会越来越大,设备拉不动;OCSP 需要在线查询,弱网设备常失败。务实做法是短有效期证书(如 90 天)配合自动续签,把吊销问题转化为续签失败问题,再用云端黑名单兜底。跨设备的认证与授权设计,与后端服务的认证体系同源,可参照 OAuth2 与 JWT 的成熟实践。
5. 安全启动与信任根
安全启动解决的是「设备启动的每一行代码都可信吗」。信任根(RoT)是一段不可篡改的 Boot ROM 代码与固化在 eFuse 里的公钥哈希,它构成信任链的起点。
信任链是逐级校验的:Boot ROM 校验一级引导(bootloader)的签名,一级引导校验二级引导,二级引导校验应用固件。任何一级校验失败就停止启动或回退到出厂固件。以 ESP32 Secure Boot v2 为例,RSA-3072 公钥摘要烧进 eFuse,固件用私钥签名,启动时 ROM 用公钥验签。
- Flash 加密:固件与数据在 Flash 上以 AES-256-XTS 加密,密钥来自 eFuse,读出 Flash 也拿不到明文。
- A/B 分区:新固件写入备用分区,校验通过后切换,失败自动回滚,避免变砖。
- 防回滚计数器:单调递增的版本号写在 eFuse,拒绝安装低版本固件,堵住「降级到有漏洞版本」的攻击。
- TrustZone:Cortex-M 用 TrustZone-M + TF-M 跑安全服务,Cortex-A 用 TrustZone + OP-TEE 隔离可信执行环境。
信任链的传递关系可以画成一条单向校验链,每一级只信任上一级的公钥摘要:
Boot ROM (不可改, 固化公钥摘要)
| 验签
v
一级引导 Bootloader (RSA-3072 签名)
| 验签
v
二级引导 / 分区表
| 验签
v
应用固件 App (A/B 分区, 防回滚计数器)
| 度量
v
运行时安全服务 (TF-M / OP-TEE) + 加密 NVS
需要提醒的是,安全启动只保护「启动路径」,不保护运行时。Flash 加密能防离线读取,但设备运行时密钥在内存里,能物理接触的攻击者仍可能通过侧信道或故障注入攻击。
6. 固件与调试口加固
量产固件的加固清单:
- 关闭 JTAG/SWD:MCU 设置读保护等级(STM32 的 RDP Level 2 不可逆地关闭调试),或直接熔断调试 eFuse。
- 禁用 UART 登录与 shell:生产固件不应保留 root shell 与命令行,只留受控的诊断接口。
- 移除调试符号与密钥:发布构建剥离符号表,绝不把私钥、测试口令编进固件。
- 代码签名:固件包在发布前签名,设备侧验签后才安装。
- 防拆检测:外壳开关触发时擦除密钥,防止物理提取。
不同芯片的调试保护强度差异很大,选型时要看清:
| 保护机制 | 典型芯片 | 强度 | 备注 |
|---|---|---|---|
| RDP Level 1 | STM32 | 中 | 有降级读取漏洞史 |
| RDP Level 2 | STM32 | 高 | 不可逆,彻底关闭调试 |
| CRP | NXP LPC | 中 | 分级,可部分解除 |
| eFuse 熔断 | ESP32 | 高 | 一次性,不可恢复 |
| 读保护 + 加密 | 多数 MCU | 中高 | 需配合 Flash 加密 |
STM32 的 RDP Level 2 一旦启用就无法再通过调试口访问 Flash,也无法降回 Level 1,属于不可逆操作,量产前务必确认。相反,很多团队为了「方便返修」保留 Level 1,攻击者可以用 Level 1 的降级读保护漏洞把整个 Flash 读出来。
7. 网络与平台侧加固
设备进网后,平台侧的加固同样重要。
- 最小权限 ACL:按设备粒度授权 Topic,设备只能发布自己的遥测、订阅自己的命令,禁止通配符跨设备订阅。
- TLS 强制:拒绝明文 MQTT,只开放 8883/443,1883 仅在内网回环。
- 限流与防重放:按设备 ID 限制消息速率,指令带 nonce 与时间戳,服务端校验窗口。
- 网络分段:设备 VLAN 与办公网隔离,只允许出站到 Broker,禁止设备间横向通信。
- 异常检测:监控单设备消息量突增、异地登录、证书异常,及时告警。
一个常见的越权场景是:平台给设备签发的 token 权限过宽,攻击者拿到一台设备的凭据后,用通配符订阅 devices/+/telemetry,就能读到全平台的数据。Topic 授权必须精确到设备自身。
网关侧可以用防火墙把「设备只能出站到 Broker」这条规则固化下来,禁止设备之间横向通信:
#!/bin/sh
set -eu
iptables -P FORWARD DROP # 默认丢弃转发
iptables -A FORWARD -i iot0 -o wan0 -p tcp --dport 8883 -j ACCEPT # 只放行 MQTT TLS
iptables -A FORWARD -i iot0 -o wan0 -p udp --dport 5684 -j ACCEPT # 放行 CoAP DTLS
iptables -A FORWARD -i iot0 -o iot0 -j DROP # 禁止设备间通信
iptables -A FORWARD -i iot0 -j DROP # 其余出站一律拒绝
8. 隐私与合规
合规不是负担,而是把安全需求外部化、可验收化的工具。
- ETSI EN 303 645:消费级 IoT 的十三条基线,包括禁止通用默认口令、漏洞披露渠道、软件更新周期、数据最小化、通信加密等。
- IEC 62443:工业控制系统的安全标准,分 4 个层级,强调分区与管道(zones and conduits)。
- NIST IR 8259:美国联邦采购 IoT 的基线能力清单,与 ETSI 高度重叠。
- PSA Certified:ARM 主导的 IoT 安全认证,分 Level 1/2/3,Level 3 要求抗物理攻击。
- 欧盟 CRA(Cyber Resilience Act):对含数字元素产品强制安全要求,要求提供 SBOM 与安全更新支持期,违规可罚全球营业额比例。
- GDPR:个人数据处理需最小化、可删除、可导出,智能音箱、摄像头、可穿戴尤其敏感。
合规审查时最常被问的三件事:漏洞怎么披露、设备能更新几年、采集了哪些个人数据。
| 标准 | 适用范围 | 关键要求 |
|---|---|---|
| ETSI EN 303 645 | 消费级 IoT | 13 条基线,禁默认口令 |
| IEC 62443 | 工业控制 | 分区与管道、安全等级 |
| NIST IR 8259 | 联邦采购 | 设备能力基线清单 |
| PSA Certified | 芯片/模组 | L1/L2/L3 分级认证 |
| 欧盟 CRA | 含数字元素产品 | SBOM + 安全支持期 |
9. 漏洞响应与安全更新
没有哪台设备是「一次加固、终身安全」的。漏洞响应能力是安全的一部分。
- SBOM:为固件生成软件物料清单,记录所有第三方库与版本,CVE 爆发时能秒级定位受影响设备。
- CVE 跟踪:订阅所用组件的安全公告,建立内部漏洞库。
- 安全公告渠道:给用户一个可订阅的漏洞披露入口(security.txt、邮件列表),承诺响应时限。
- 更新通道安全:OTA 走签名校验与加密传输,详见 OTA 固件升级 。
- 不可更新设备:如果设备无法远程升级(如纯 NB-IoT 无 OTA 能力),必须在设计阶段就把风险降到最低,并在采购合同中明确安全支持期。
一个最小可用的 SBOM 片段如下,CI 每次构建产出并归档,CVE 爆发时用组件名与版本做关联查询:
{
"bomFormat": "CycloneDX",
"specVersion": "1.5",
"metadata": {
"component": {
"name": "iot-gateway-firmware",
"version": "2.4.1",
"type": "firmware"
}
},
"components": [
{ "name": "mbedtls", "version": "3.5.1", "type": "library" },
{ "name": "lwip", "version": "2.2.0", "type": "library" },
{ "name": "cjson", "version": "1.7.17", "type": "library" },
{ "name": "freertos", "version": "10.5.1", "type": "library" }
]
}
CRA 与 ETSI 都要求厂商声明「安全支持期」,一般为产品上市后 5 年。做不到就不要承诺。
10. 加固配置示例
下面给出两段可直接改造使用的配置。第一段是 ESP32 量产烧录的熔断与安全启动脚本,注意 eFuse 熔断不可逆,务必在样机验证后再上量产线。
#!/bin/sh
set -eu
esptool.py read_flash 0x0 0x1000 boot_backup.bin # 熔断前先备份
espsecure.py generate_signing_key secure_boot.pem # 生成安全启动签名密钥
espsecure.py sign_data --version 2 --keyfile secure_boot.pem --output bootloader_signed.bin bootloader.bin
espefuse.py burn_efuse SECURE_BOOT_EN 1 # 启用 Secure Boot v2
espefuse.py burn_efuse FLASH_CRYPT_CNT 0x7 # 启用 Flash 加密(奇偶计数)
espefuse.py burn_efuse DIS_DOWNLOAD_MODE 1 # 熔断 UART 下载模式
espefuse.py burn_efuse DIS_USB_JTAG 1 # 熔断 USB-JTAG 调试
espefuse.py burn_efuse DIS_DIRECT_BOOT 1 # 禁止直接从 Flash 启动旧镜像
第二段是 MQTT Broker 的按设备粒度授权,用变量 ${clientid} 把权限绑定到连接身份,杜绝通配订阅。
authorization:
no_match: deny
sources:
- type: file
enable: true
rules:
- topic: "devices/${clientid}/telemetry" # 只能发布自身遥测
action: publish
permission: allow
- topic: "devices/${clientid}/cmd/#" # 只能订阅自身命令
action: subscribe
permission: allow
- topic: "devices/+/telemetry" # 显式拒绝通配订阅
action: subscribe
permission: deny
listeners:
ssl:
bind: "0.0.0.0:8883"
ssl_options:
verify: verify_peer # 强制 mTLS 客户端证书
fail_if_no_peer_cert: true
11. 安全测试与验证
加固做完要能验证,否则只是自我安慰。
- 静态扫描:firmware 用 binwalk 拆包、strings 找密钥、checksec 查保护;源码用 CodeQL、Semgrep。
- 动态测试:网络侧用 nmap 扫开放端口,用 mqtt-pwn、Mosquitto 客户端试越权订阅。
- 故障注入:对高安全设备做电压毛刺、时钟毛刺,验证安全启动是否真的拦住。
- 渗透测试:至少在产品定型前做一次第三方渗透,覆盖设备、App、云三条链路。
- 回归:把上面每一项做成 CI 里的自动检查,固件每次构建都跑一遍。
常用工具与对应环节:
| 环节 | 工具 | 用途 |
|---|---|---|
| 固件拆包 | binwalk、firmware-mod-kit | 提取文件系统与内核 |
| 凭据扫描 | strings、trufflehog | 找硬编码密钥与口令 |
| 二进制保护 | checksec、readelf | 查 NX、PIE、Canary |
| 端口扫描 | nmap、masscan | 发现暴露的管理口 |
| MQTT 越权 | mqtt-pwn、mosquitto_sub | 试通配订阅与重放 |
| 故障注入 | ChipWhisperer、Riscure | 电压/时钟毛刺攻击 |
12. 纵深防御与安全运营
单点加固不可靠,要分层。物理层靠熔断与防拆,硬件层靠 SE 与 TPM,固件层靠安全启动与签名,网络层靠 TLS 与分段,平台层靠鉴权与限流,运营层靠监控与响应。攻击者突破一层,还有下一层。
安全运营的落地:设备资产台账(谁在哪、什么固件版本)、证书有效期监控、异常行为告警、漏洞 SLA(高危 7 天、中危 30 天)。把这些接进现有的可观测体系,安全事件和业务告警走同一套通知链路,避免「安全团队不知道设备在线率掉了」。
从攻击者视角做一次红队推演,往往能发现纸面加固的漏洞:他会先扫暴露端口找默认口令,再尝试物理接触读 Flash,然后看能否伪造设备上报,最后试探平台越权。每一环都问一句「拦住了吗、拦不住会怎样、多久能发现」。安全运营的成熟度不看买了多少产品,而看「从入侵到发现」的平均时间(MTTD)和「从发现到阻断」的平均时间(MTTR)。
权衡取舍
| 维度 | 高安全方案 | 低成本方案 | 建议 |
|---|---|---|---|
| 身份 | X.509 + SE | 一机一密 | 高价值设备用证书,消费级可一机一密 |
| 密钥存储 | ATECC608A / SE050 | Flash 加密 | 有物理接触风险必须上 SE |
| 启动 | 安全启动 + A/B + 防回滚 | 仅签名校验 | 联网可升级设备上完整链 |
| 调试口 | 熔断 JTAG | 保留读保护 | 量产必熔断,返修走替换 |
| 传输 | mTLS + TLS 1.3 | PSK + TLS 1.2 | 弱网低功耗用 DTLS + OSCORE |
核心原则:安全强度要与资产价值和攻击者能力匹配,不要为了「最安全」把 BOM 成本推到产品卖不动,也不要在门锁上省掉安全芯片。
常见坑清单
- 现象:设备出厂全是同一口令。原因:为了方便产线批量烧录。规避:出厂随机一机一密,首启动强制改密。
- 现象:固件被读出密钥。原因:私钥明文存 Flash。规避:密钥进 SE 或 TPM,永不导出。
- 现象:设备只能降级不能升级。原因:没做防回滚计数器。规避:eFuse 单调版本号 + 拒绝低版本。
- 现象:升级失败变砖。原因:单分区原地刷写。规避:A/B 分区 + 校验后切换 + 自动回滚。
- 现象:一台设备泄露导致全平台数据被读。原因:Token 权限过宽、允许通配订阅。规避:Topic 精确到
${clientid}。 - 现象:TLS 被中间人。原因:未校验服务端证书或未固定 CA。规避:证书链校验 + CA pinning。
- 现象:合规审查拿不出 SBOM。原因:构建流程没生成物料清单。规避:CI 自动产出 SBOM 并归档。
- 现象:漏洞爆发时不知道哪些设备受影响。原因:没有固件版本台账。规避:设备影子记录固件版本并实时更新。
- 现象:安全启动开了但被物理绕过。原因:调试口未关,攻击者直接读 Flash。规避:熔断 JTAG/SWD 与下载模式。
小结
物联网安全不是买一个安全芯片就完事,而是从制造、入网、运行到退役的全生命周期工程。核心是三件事:让设备有不可伪造的身份(SE/TPM + 证书),让每一行启动代码可信(安全启动 + 签名 + 防回滚),让平台按最小权限运行(Topic 级授权 + 限流 + 监控)。这三件事做不到位,后面的合规、隐私、漏洞响应都是空中楼阁。
对大多数团队来说,务实路线是:先堵住默认口令和暴露端口这两个「Mirai 级」问题,再补上 TLS 与设备身份,然后做安全启动与 OTA 签名,最后才是合规认证与第三方渗透。每一步都能独立交付价值,不必等一个「大而全」的安全改造。
下一步建议沿着两条线深入:设备侧看 OTA 固件升级 把更新通道的安全闭环补齐,平台侧看 MQTT 协议与主题设计 与 网络安全 把鉴权、分段与入侵检测做扎实。
继续阅读
探索更多技术文章
浏览归档,发现更多关于系统设计、工具链和工程实践的内容。