1. MQTT 未授权访问检测与利用
实验环境与目标
本例在一台隔离的 Linux 主机上搭建 Mosquitto 代理,故意开启匿名访问,然后从另一台主机(或同一主机的不同终端)用 mosquitto_sub 与 mosquitto_pub 验证:未携带任何用户名/口令的客户端能否成功订阅与发布。最后通过抓包分析 CONNECT 与 SUBSCRIBE 报文中认证字段的缺失情况。
实验拓扑与关键端口如下:
搭建 Mosquitto 并开启匿名访问
在代理主机上安装 Mosquitto 后,编辑配置文件 /etc/mosquitto/mosquitto.conf,关键配置如下:
# /etc/mosquitto/mosquitto.conf
listener 1883 0.0.0.0
allow_anonymous true
# 不配置 password_file,不配置 acl_file
重启服务并确认监听状态:
sudo systemctl restart mosquitto
sudo ss -tlnp | grep 1883
# 预期输出:LISTEN 0 100 0.0.0.0:1883 0.0.0.0:* users:(("mosquitto",pid=...))
allow_anonymous true 且无 ACL 会导致任意客户端读写全部主题。未授权订阅验证
在攻击者主机上执行订阅命令,不提供任何认证参数:
mosquitto_sub -h 192.168.56.10 -p 1883 -t '#' -v
参数说明:-h 指定代理地址,-p 指定端口,-t '#' 订阅所有主题,-v 显示主题名。若连接成功且无报错,终端会保持等待状态,说明未授权订阅已生效。
未授权发布验证
在另一个终端(或合法设备模拟端)执行发布:
mosquitto_pub -h 192.168.56.10 -p 1883 -t 'sensors/temp' -m '{"device":"sensor-01","temp":36.5}'
此时订阅终端应立即输出:
sensors/temp {"device":"sensor-01","temp":36.5}
这证明攻击者无需任何凭据即可向任意主题发布消息,订阅者会正常收到。若将主题改为 cmd/device-01 并发布控制指令,同样会被下游设备接收,形成指令注入风险。
抓包分析认证缺失点
在攻击者主机上对 1883 端口抓包:
sudo tcpdump -i any -w mqtt_anon.pcap port 1883
复现一次订阅与发布后停止抓包,用 Wireshark 打开并过滤 mqtt。重点观察两个报文:
- CONNECT 报文:Connect Flags 字节中 Username Flag 与 Password Flag 均为 0,载荷中只有 Client ID,没有 User Name 和 Password 字段。代理端因
allow_anonymous true直接返回 CONNACK 并置 Return Code 为 0(连接已接受)。 - SUBSCRIBE 报文:报文本身不携带任何认证字段,认证完全依赖 CONNECT 阶段。由于 CONNECT 阶段未认证,SUBSCRIBE 的 Topic Filter 为
#时代理不做 ACL 校验,直接返回 SUBACK 授予 QoS 0。
由此可归纳出认证缺失点:MQTT 3.1.1 的认证只发生在 CONNECT 阶段,SUBSCRIBE/PUBLISH 不重复认证;当代理配置为匿名允许且无 ACL 时,任何网络可达的客户端都能完成全主题读写。
检测与加固要点
| 检测项 | 命令/方法 | 未授权特征 |
|---|---|---|
| 匿名连接 | mosquitto_sub -t '#' -v 无 -u/-P | 成功收到消息 |
| 匿名发布 | mosquitto_pub -t test -m x 无 -u/-P | 订阅端收到 test |
| CONNECT 标志 | Wireshark 查看 Connect Flags | Username/Password Flag=0 |
| SUBACK 返回 | Wireshark 查看 SUBACK | 对 # 返回 QoS 0 授予 |
加固方向:设置 allow_anonymous false,配置 password_file 启用用户名口令认证,并通过 acl_file 限制每个客户端可订阅/发布的主题范围。完成加固后重复上述命令,未携带凭据的连接应被拒绝,CONNACK 返回码非 0。