跳到主要内容

IoT 消息协议:加密连接为何仍可能执行伪造指令

一条控制消息经 TLS 送达设备,只能说明它通过某条受保护的连接传输。设备还需要判断消息由谁发出、是否有权控制这个对象、内容是否被转发者改变,以及这条动作是否已经执行过。把这些判断都交给“用了加密协议”,会留下不同层次的缺口。

实操:检查实际部署的 MQTT 连接、主题和设备动作​

准备产品测试环境中真实的 Broker、两台设备的主题、设备身份与控制端身份。主题来自部署配置、设备日志或自己的 App 通信,不能由猜测的路径代替。以下选择双向 TLS 的部署,使用测试设备合法签发的 CA、客户端证书与私钥;用户名口令部署按客户端文档使用配置文件,不把真实密码写进文章或命令记录。

先取得连接材料,再选择测试身份​

项目开发者从设备注册或证书签发流程导出测试身份,在 Broker 配置中确认监听、CA 与证书主体映射。黑盒研究先从自己的 App、设备日志或固件配置定位 Broker 和主题:抓包能看到目标主机不代表已经取得身份,TLS 流量也不会直接提供客户端私钥。设备密钥不可导出时,保留真实设备作为发送端,在合法控制端观察结果,不把“缺少私钥”绕成任意客户端可连接。

把 Broker 地址、协议版本、认证方式、A/B 主题和动作来源记到研究记录中。证书认证与用户名口令认证选择对应的一条路径;下文的 mTLS 命令只有在这套材料已齐全时执行。

确认 TLS 身份,再订阅自己的遥测​

在安装了 mosquitto-clients 的电脑设置实际目标和主题:

export MQTT_HOST=替换为测试Broker域名
export MQTT_TELEMETRY_A=替换为设备A遥测主题
export MQTT_COMMAND_A=替换为设备A控制主题
mosquitto_sub -h "$MQTT_HOST" -p 8883 \
--cafile ca.pem --cert device-a.crt --key device-a.key \
-t "$MQTT_TELEMETRY_A" -q 1 -v -d -W 15

端口、文件与主题均来自实际部署;非 8883 监听按配置调整。核对 CONNECT/SUBACK、实际主题与载荷。没有消息时先确认设备正在上报、主题正确、证书身份与 ACL 对应,不能把等待超时直接判成授权拒绝。Mosquitto 客户端文档

先订阅,再通过官方 App 或设备本身触发一次可识别的状态上报,记下时间和设备标识。客户端 -d 输出按以下顺序解释:

观察到的阶段此时已经确认下一步需要看什么
TCP 或 TLS 连接失败尚未完成 MQTT 会话监听地址、证书链、客户端证书要求
收到成功的 CONNACKBroker 接受本次连接主题订阅或发布权限
SUBACK 接受目标过滤器本次订阅建立目标设备是否上报、实际交付的主题
收到匹配的 PUBLISH消息到达观察端载荷是否属于本次操作及目标设备
设备回读反映目标动作设备行为已经改变执行主体和当前业务授权是否正确

MQTT 3.1.1 的 SUBACK 返回码 0x80 表示订阅失败;收到成功回执却暂时没有消息,应检查发布时机、过滤器和转发策略。订阅前已经发出的普通消息不会因为后来订阅而自动重发;保留消息和持久会话另行记录。MQTT 3.1.1,3.9 节

一次只改变一个权限条件​

用设备 A 的同一身份依次尝试 A 的遥测订阅、B 的遥测订阅、A 的控制发布和 B 的控制发布。每项先确认产品给该身份的预期权限;有些设备只允许发布自己的遥测,本来就不该订阅。

发布验证使用产品已经定义的无害动作载荷,例如 App 实际发出的状态查询,保存其原始消息为 captured-command.json。不能把未知格式直接发到门锁、电机或升级主题。在控制端身份正常执行成功后,再切换到设备 A 身份发送同一消息:

mosquitto_pub -h "$MQTT_HOST" -p 8883 \
--cafile ca.pem --cert device-a.crt --key device-a.key \
-t "$MQTT_COMMAND_A" -q 1 -d -f captured-command.json

结合 Broker 的认证主体、ACL 日志、合法观察端与设备回执判定。MQTT 3.1.1 的发布完成并不可靠证明授权通过;MQTT 5 的失败原因也要与实际部署版本对应。

使用部署中的 ACL 做修复对照​

管理员导出当前生效的授权规则,找到上述连接身份映射到的主题范围。收窄越权规则后重新连接,以同一身份、同一主题和同一载荷复测:错误发布应被拒绝,原有合法遥测仍应成功。不要新建一套本地 Broker 来替代产品的实际映射。Mosquitto 的传统 acl_file 与新插件配置按部署版本选择。配置文档

最后撤销设备身份或转移所有权,保留旧连接重试,再断线重连重试。对于保留消息和持久会话,检查新主人上线后是否收到旧动作;消息被交付与设备实际执行需要分开记录。

成立前提与能力变化​

消息攻击需要到达 Broker、代理或设备接收端,并突破连接认证、主题授权、对象认证或业务新鲜度中的至少一处。链路可以是“取得可用连接身份 → 向目标控制主题发布 → 消息被转发 → 设备执行动作”。每一步都要有证据;连接成功不能替代最后两步。

MQTT 的连接身份不能代替主题权限​

MQTT 的 Broker 接收发布消息,并向匹配订阅的客户端转发。Topic 是路由名称,不是秘密;知道某个设备的主题路径,也不应意味着获得发布权限。Client ID 主要标识连接与会话,其可信性需要与认证及授权规则配合建立。

OASIS MQTT 5.0 规范分别讨论认证、授权和安全风险,并定义 QoS、保留消息与会话行为。协议提供这些机制,但部署方仍需要配置客户端能发布、订阅和接收哪些资源。MQTT 5.0 规范

例如,一台温度传感器可以上报自己的测量值,但不应因此能够发布门锁控制消息。订阅权限与发布权限需要分别约束,网关或桥接服务还必须保持租户与设备身份的对应关系。

消息队列会让旧授权继续产生影响​

保留消息和离线队列有助于设备重连后恢复状态,但也会把历史指令带到新的执行时刻。设备转售、分享撤销或固件升级后,队列里的消息可能对应已经失效的所有权和策略。

QoS 2 的“恰好一次”描述的是协议消息交付语义,不能阻止应用层重新创建语义相同的命令。重新发送等价命令,或者在确认丢失后再次请求同一动作,都需要业务层判断是否可以执行。

消息设计可以包含动作 ID、目标设备、授权主体、有效期与授权代际。设备检查这些字段后,再按业务语义处理重复消息:设置目标温度与执行一次付款、开门脉冲,不适合使用同一套重试规则。字段只有在受到认证保护,并且接收方保存必要状态时,才能承担安全作用。

Broker 通过认证,也可能转发越权消息​

Mosquitto 文档展示了密码、证书与访问控制配置的分工。开启 TLS 不等于要求客户端提交证书;要求证书也不等于所有主题已经正确隔离。ACL 中使用用户名、客户端标识或模式变量时,需要核对这些值是否来自可信的认证关系。Mosquitto 配置文档

Nooie 的历史披露给出了可以对照的真实字段:设备上线消息 /device/init 包含设备 uuid 与账号 uid,控制消息路由为 /device/<uuid>/cmd,媒体目标由消息中的 cmd 和 url 参数参与指定。研究中的 Broker 允许未认证连接,设备又接受控制消息改变媒体接收位置,形成“标识泄露 → 消息投递 → 上传目的地改变”。这些是原始报告中的路径,不作为当前公网服务的测试目标。Nooie 原始披露

对自己的产品,用合法上线记录确认标识来自哪里,再检查普通设备身份能否投递控制消息,以及设备为何接受目标地址。更换接收地址可能暴露实时媒体,越界消息是否被转发与接收方是否被业务策略认可应分别记录。披露记录的型号为 PC100A v1.3.88、IPC007A-1080P v2.1.94,页面在 2022 年 4 月补充厂商确认已发布修复;不能把历史路径当作当前型号的已验证缺陷。

将主题权限与业务授权放在不同层检查​

可用一个假设系统说明权限分工。传感器 A 的遥测消息位于 tenants/t1/devices/a/telemetry,控制消息位于同设备的 commands 路径。这些路径只是本文示例,不是协议规定。

Broker 应把连接中已经认证的主体映射到允许的资源,不能直接信任消息正文里自报的 device_id。若一个连接能发布任意设备的 commands,即使设备端验证消息来自可信 Broker,错误权限仍会被正常转发。

设备端则需要判断业务状态。例如一条消息有合法来源,却要求旧主人继续开锁,或者目标设备与当前所有权代际不符,就应由业务检查拒绝。云端授权与设备检查承担不同职责,不能互相假设对方已经完成所有判断。

撤销设计还要处理保留消息和共享订阅。应明确哪些队列由哪个主体持有、授权变化后是否清理或重新校验,以及桥接服务是否把多个租户混入同一个高权限身份。这里需要测试的是具体部署,不能从协议支持某功能推断部署已经正确配置。

修复应对照实际生效的主体、主题与消息​

在部署中找到认证主体到资源规则的实际映射,核对发布、订阅和接收是否分别约束到必要范围。修复后用原设备证书、原主题和原请求重测,同时保留合法遥测与控制的正向结果。

业务重放要使用产品真实的命令标识、会话或计数器,观察重复动作与所有权变化后旧消息的执行结果。Broker ACL 与业务检查分别留下证据,不能用一段未部署的配置代替修复完成。

CoAP 需要明确保护到哪一端​

CoAP 可通过 DTLS 保护传输,也可以使用 OSCORE 对消息对象提供端到端保护。两者需要结合代理和网关拓扑选择:如果保护在网关终止,网关之后的消息信任就需要另外说明。

RFC 8613 定义 OSCORE 的安全上下文、序列号与重放保护等机制。部署时,重启后的序列号与接收窗口状态也要处理正确;重复使用安全上下文中的序列号,可能影响协议要求的安全性质。RFC 8613

对象级保护仍不自动证明业务授权。消息确实来自某个合法设备,与该设备有权修改另一个设备的配置,是不同命题。

用权限矩阵和断线场景验证​

把前文的身份、主题、发布、订阅和实际交付结果放到同一矩阵,再补齐桥接与其他租户身份。业务所有权变化后的设备执行测试见设备绑定,避免将 Broker 转发权限与设备当前主人权限合并为一个结果。

主题与资源权限缺失可以对照未授权访问;跨请求状态变化的通用问题见逻辑缺陷。

关联阅读:设备身份与绑定、App 与云 API 控制链路。