4. 授权与访问控制漏洞:通配符订阅滥用、Topic权限划分不当、超级用户权限过大

授权与访问控制,说白了就是决定「谁可以干什么」。MQTT 的 Topic 结构天然是树形的,这给了我们很大的灵活性,但也埋下了不少坑。我见过太多项目,因为权限没管好,整个系统就像没锁门的仓库。

这一章,我们重点聊三个最常出问题的地方:通配符订阅、Topic 权限划分,还有超级用户。嗯,咱们一个一个来看。

4.1 通配符订阅滥用

MQTT 的通配符 +(单层)和 #(多层)本来是为了方便订阅,但用不好就是灾难。

⚠️ 核心风险:客户端通过通配符订阅,可以「越级」看到本不该看到的 Topic 数据。

举个例子。你有个智能家居系统,每个房间的传感器数据放在 house/room1/temp、house/room2/temp 这样的 Topic 下。如果某个房间的客户端订阅了 house/+/temp,它就能看到所有房间的温度。这还算轻的。

我曾经在一个项目中遇到过,某个设备订阅了 #,结果把整个系统的内部状态、OTA 升级指令、甚至管理员心跳包全收走了。你想想看,这要是被恶意利用,后果不堪设想。

4.1.1 通配符滥用的典型场景

场景 订阅 Topic 风险等级 说明
全局监听 # 极高 接收所有消息,包括系统级 Topic
跨租户窥探 tenant/+/data 高 可访问其他租户的数据
越级控制 +/device/cmd 高 可能向非授权设备发送指令
日志泄露 system/log/# 中 暴露系统运行日志

4.1.2 防护措施

  • 最小通配符原则:非必要不使用 #,能用 + 就别用 #。
  • 白名单订阅:在 Broker 端配置允许订阅的 Topic 列表,拒绝通配符的「越界」行为。
  • 动态 ACL 检查:每次订阅请求都校验客户端身份与 Topic 的匹配关系。
💡 我的习惯:在 Broker 的 ACL 配置里,我会明确禁止普通设备订阅以 $ 开头的系统 Topic,同时限制 # 只能由运维管理端使用。

4.2 Topic 权限划分不当

Topic 权限划分,核心是「谁可以发布,谁可以订阅」。很多系统只做了简单的用户名密码认证,但 Topic 级别的权限控制却形同虚设。

我见过一个工业 IoT 项目,所有设备都用同一个凭证连接 Broker,然后通过 Topic 前缀来区分功能。结果呢?一个温度传感器居然可以发布到 actuator/valve/ctrl 这个 Topic 上。这不是乱套了吗?

4.2.1 权限划分的常见错误

  1. 所有设备共享同一个凭证:无法区分设备身份,权限控制无从谈起。
  2. Topic 命名与权限脱钩:Topic 结构设计得很好,但 ACL 规则没跟上。
  3. 发布与订阅权限混为一谈:允许设备订阅某个 Topic,却不小心也允许它发布到该 Topic。
  4. 缺乏层级继承:父 Topic 的权限没有正确下放到子 Topic。

4.2.2 正确的权限划分模型

我建议采用「设备类型 + 设备 ID + 功能域」的三层 Topic 结构,配合细粒度的 ACL。

# Topic 结构示例
sensor/{device_id}/temp      # 温度传感器只发布
actuator/{device_id}/valve   # 执行器只订阅
admin/{device_id}/config     # 管理端可发布和订阅

# ACL 规则示例(以 Mosquitto 为例)
# 允许传感器发布自己的温度数据
user sensor_001
topic write sensor/sensor_001/temp

# 允许执行器订阅自己的控制指令
user actuator_001
topic read actuator/actuator_001/valve

# 禁止传感器订阅任何 actuator Topic
user sensor_001
topic deny read actuator/#
🔑 关键原则:每个 Topic 的发布者和订阅者应该是固定的、可预期的。如果一个 Topic 既可以被 A 发布又可以被 B 发布,那就要小心了——这往往是权限划分不清的信号。

4.3 超级用户权限过大

超级用户(Super User)在 MQTT 里通常意味着「不受 ACL 限制」。这个角色本意是给管理员用的,但很多系统把它用滥了。

我记得有一次做安全审计,发现某个 Broker 上 80% 的客户端都配置了超级用户权限。问运维为什么,他说「这样省事,不用配 ACL 了」。你想想看,这跟把公司大门钥匙发给每个员工有什么区别?

4.3.1 超级用户滥用的后果

  • 权限失控:超级用户可以订阅任何 Topic,包括其他租户的敏感数据。
  • 审计困难:所有操作都归到超级用户头上,出了问题根本查不到是谁干的。
  • 攻击面扩大:一旦某个超级用户凭证泄露,攻击者就能控制整个 Broker。

4.3.2 超级用户的使用规范

角色 是否应使用超级用户 替代方案
Broker 管理员 是(仅限运维操作) 使用独立凭证,操作后立即禁用
普通设备 否 使用设备级凭证 + 细粒度 ACL
后端服务 否 使用服务账号 + 最小权限原则
调试工具 临时可用 调试完成后立即撤销权限
⚠️ 避坑指南:我曾经在项目中因为图省事,给所有测试设备都配了超级用户权限。结果测试结束后忘了回收,生产环境上线后,某个测试设备因为固件 bug 开始乱发消息,差点导致整个产线停机。从那以后,我再也不敢随便开超级用户权限了。

4.4 授权与访问控制的整体架构

下面这张图,是我个人习惯用的授权与访问控制架构。它把认证、授权、审计三个环节串了起来。

MQTT 授权与访问控制架构 MQTT 客户端 MQTT 客户端 MQTT 客户端 认证层(身份验证) 用户名/密码 | 证书 | Token 授权层(访问控制) ACL 规则 | Topic 白名单 | 通配符限制 发布/订阅权限分离 | 超级用户管理 审计层(日志与监控) 操作日志 | 异常告警 | 权限变更记录 核心原则:认证先行 → 授权细化 → 审计闭环

4.5 实战建议

说了这么多,最后给几个落地建议。

  1. Topic 设计阶段就考虑权限:别等系统上线了再补 ACL,那时候改起来成本很高。
  2. 默认拒绝:ACL 的默认策略应该是拒绝所有,然后按需开放。
  3. 定期审计:我建议每个月跑一次权限审计脚本,检查有没有「越权」的订阅或发布。
  4. 超级用户凭证单独管理:不要写在配置文件里,用密钥管理服务(KMS)来托管。
💡 一个小技巧:在测试环境里,我会故意用一个普通设备凭证去订阅 #,如果成功了,说明 ACL 配置有问题。这个「自检」习惯帮我发现过好几次配置遗漏。

授权与访问控制,说白了就是「把门看好」。通配符别乱用,权限别乱给,超级用户别乱开。做到这三点,你的 MQTT 系统至少能挡住 80% 的权限相关攻击。