4、MQTT安全威胁分析:中间人攻击、重放攻击、拒绝服务攻击、未授权访问与数据泄露

MQTT 协议设计之初,主要考虑的是低带宽、低功耗的物联网场景。说实话,那时候大家对安全的重视程度远不如现在。我最早接触 MQTT 是在一个智能楼宇项目里,当时觉得 Broker 能跑起来、消息能收发就万事大吉了。直到后来帮一家工厂做产线数据采集,才真正意识到——MQTT 如果不做安全加固,简直就是给攻击者留了一扇敞开的门。

这一章,我们就来拆解 MQTT 最常见的五类安全威胁。你想想看,如果连这些风险都认不全,后面的防护策略也就无从谈起。

核心观点:MQTT 的安全威胁并非孤立存在,它们往往相互配合、层层递进。一次成功的攻击,通常是从嗅探开始,到中间人篡改,最后实现数据窃取或系统瘫痪。
MQTT 安全威胁全景图 MQTT Broker 中间人攻击 MITM 重放攻击 Replay 拒绝服务攻击 DoS 未授权访问 Unauthorized 数据泄露 Data Leakage 说明:数据泄露往往是其他攻击的最终目的,而中间人攻击和重放攻击又常被用作未授权访问的跳板。 五类威胁相互关联,单一防护不足以应对组合攻击。

4.1 中间人攻击(MITM)

中间人攻击,说白了就是攻击者悄悄插到客户端和 Broker 之间,假装自己是 Broker 跟客户端通信,同时又假装自己是客户端跟 Broker 通信。两边都被蒙在鼓里,所有消息都经过攻击者之手。

我记得有一次做渗透测试,客户用的是明文 MQTT,没有 TLS。我直接在交换机上做了个端口镜像,用 Wireshark 抓包,用户名、密码、传感器数据一览无余。更可怕的是,我还可以在中间修改消息内容——比如把温度传感器的 65°C 改成 35°C,报警系统就永远不会触发。

⚠ 关键风险:MQTT v3.1.1 和 v5.0 协议本身不提供传输层加密。如果不启用 TLS,所有 CONNECT 报文中的用户名和密码都是明文传输的。攻击者只要接入同一网络,就能轻松实施 MITM。

为什么 MITM 在 MQTT 场景里特别危险?因为物联网设备往往部署在物理不可控的环境中——比如路边的传感器、工厂车间的 PLC。攻击者可以物理接入网络,或者通过 Wi-Fi 钓鱼的方式让设备连上恶意热点。

防护手段其实不复杂:强制启用 TLS,并且客户端要验证 Broker 的证书。我见过不少项目虽然启用了 TLS,但客户端代码里把证书验证给关了——这就跟没穿衣服出门一样,形同虚设。

4.2 重放攻击

重放攻击,攻击者不需要破解你的加密,也不需要知道消息内容。他只需要把之前截获的合法消息,原封不动地再发一遍。

举个例子,你想想看:一个智能门锁,每次开门都发送一条 MQTT 消息。攻击者抓包拿到了这条消息,虽然看不懂加密内容,但他可以在你离开后,把这条消息重新发给 Broker。如果 Broker 没有防重放机制,门就开了。

我在一个车联网项目里遇到过类似问题。车辆上报 GPS 位置,攻击者重放了一条旧的位置消息,结果车队管理系统显示车辆还在原地,实际上车已经开出去十公里了。还好我们及时发现,在消息里加了时间戳和序列号。

防护手段 原理 适用场景
消息唯一 ID 每条消息携带唯一标识,Broker 缓存已处理 ID 命令下发、控制类消息
时间戳 + 窗口 消息携带时间戳,Broker 只接受窗口内的消息 数据上报、遥测
序列号递增 客户端维护递增序列号,Broker 校验连续性 设备状态同步
一次性 Token 每次操作前获取临时 Token,用完即废 关键操作、开锁、启动
💡 我的建议:不要只依赖一种防重放机制。时间戳 + 消息 ID 的组合,是目前性价比最高的方案。我曾经在一个项目中只用时间戳,结果因为设备时钟漂移,大量合法消息被误判为重放——那叫一个头疼。

4.3 拒绝服务攻击(DoS)

MQTT 的 DoS 攻击,说白了就是让 Broker 忙到没空处理正常请求。攻击方式五花八门,但核心思路都一样——耗尽 Broker 的资源。

常见的攻击手法包括:

  • CONNECT 洪水:攻击者快速建立大量 MQTT 连接,但不发送 DISCONNECT。Broker 的连接数很快被耗尽。
  • 主题订阅爆炸:每个客户端订阅成千上万个主题,Broker 的路由表被撑爆。
  • 大消息攻击:发送超大的 PUBLISH 消息,填满 Broker 的缓冲区。
  • 遗嘱消息滥用:攻击者建立连接后突然断开,触发大量遗嘱消息,Broker 忙于处理遗嘱而无法响应正常请求。

我记得有一次帮客户做压力测试,一个普通的 Mosquitto Broker,没做任何限流配置。我用一台笔记本跑了 5000 个并发连接,Broker 直接 OOM 崩溃了。客户当时脸都绿了——他们的生产环境有 3 万多台设备。

防护要点:Broker 端必须做资源限制。连接数上限、消息大小上限、客户端订阅上限、消息速率限制,这些一个都不能少。MQTT v5.0 引入了 CONNACK 属性中的“Retain Available”和“Maximum Packet Size”,可以用来做协商限制。

4.4 未授权访问

未授权访问,就是攻击者没有合法身份,却成功连接到了 Broker 并开始收发消息。这个问题在 MQTT 里尤其普遍,因为很多开发者觉得“反正消息不重要,不用设密码”。

我见过最夸张的一个案例:某智慧农业项目,Broker 直接部署在公网上,没有用户名密码,没有防火墙限制。任何人都可以连接,可以订阅所有主题。传感器数据、灌溉控制指令,全部暴露在外。攻击者甚至可以通过发布虚假的灌溉指令,让农田在暴雨天继续浇水。

MQTT 的未授权访问通常有几种形式:

  1. 匿名连接:Broker 允许不带用户名密码的 CONNECT 报文。
  2. 弱密码:用户名密码过于简单,或者使用默认密码(admin/admin 这种)。
  3. ACL 缺失:即使有认证,但所有客户端都能订阅/发布所有主题。
  4. 凭证泄露:硬编码在固件中的用户名密码被逆向工程提取。
⚠ 避坑指南:我曾经在一个项目中,发现设备固件里直接写死了 Broker 的密码。后来这批设备被二手回收,新买家直接读出了固件,拿到了密码。整个生产环境的安全防线瞬间崩塌。记住:永远不要在固件里硬编码凭证,使用动态 Token 或证书才是正道。

4.5 数据泄露

数据泄露,往往是前面几种攻击的最终目的。攻击者通过 MITM 窃听、未授权访问订阅敏感主题、或者破解加密后读取消息内容,最终拿到有价值的数据。

MQTT 场景下的数据泄露,后果可能比传统 IT 系统更严重。为什么?因为物联网数据往往直接关联物理世界——工厂的产量数据、医院的设备状态、电网的负荷信息。这些数据一旦泄露,不仅是商业机密问题,还可能涉及生产安全、公共安全。

我记得有个做智慧水务的客户,他们的 MQTT Broker 上跑着全市的水压、水质数据。攻击者通过未授权访问订阅了所有主题,然后把这些数据卖给了竞争对手。客户花了三个月才排查清楚泄露路径,损失惨重。

数据泄露的防护,需要从三个层面入手:

层面 措施 说明
传输层 TLS 加密 防止中间人窃听,确保数据在传输过程中不可读
访问控制层 ACL + 认证 确保只有授权客户端能订阅/发布特定主题
数据层 Payload 加密 即使 Broker 被攻破,攻击者也读不懂消息内容
💡 我的经验:很多团队只做了传输层加密,觉得 TLS 就万事大吉了。但你想过没有,Broker 本身如果被攻破,TLS 保护的数据在 Broker 内存里可是明文的。所以,对于高敏感数据,我建议做端到端的 Payload 加密——客户端加密,客户端解密,Broker 只负责转发,永远看不到明文。

4.6 威胁关联分析

这五类威胁不是孤立的。我画了一张关联图,你看看就明白了:

  • 中间人攻击 → 数据泄露:MITM 直接导致数据被窃听。
  • 中间人攻击 → 重放攻击:MITM 可以截获合法消息,用于后续重放。
  • 未授权访问 → 数据泄露:攻击者直接订阅敏感主题。
  • 拒绝服务攻击 → 未授权访问:DoS 导致日志系统失效,掩盖入侵痕迹。
  • 重放攻击 → 未授权访问:重放合法凭证,绕过认证。

所以,做安全防护的时候,不能只盯着单一威胁。我见过不少团队,花了大价钱做 TLS 加密,结果 ACL 没配好,攻击者照样能通过未授权访问拿到数据。安全是一个系统工程,短板效应在这里体现得淋漓尽致。