MQTT是一种基于发布/订阅模式的”轻量级”通讯协议,该协议构建于TCP/IP协议上。它是轻量级的、开放的、简单的,并且设计得易于实现,所以这些特性特别适用于受限环境中,比如机器对机器(M2M)和物联网环境(IoT)。
发布/订阅模式
MQTT协议中有三种角色和一个主要概念,三种角色分别是发布者(PUBLISHER)、订阅者(SUBCRIBER)、代理(BROKER),还有一个主要的概念为主题(TOPIC)。
消息的发送方被称为发布者,消息的接收方被称为订阅者,发送者和订阅者发布或订阅消息均会连接BROKER,BROKER一般为服务端,BROKER存放消息的容器就是主题。发布者将消息发送到主题中,订阅者在接收消息之前需要先“订阅主题”。每份订阅中,订阅者都可以接收到主题的所有消息。
简图如下:
主要特点:
-
发布订阅模式区别于传统的客户端-服务器模式,发布者与订阅者不需要建立直接联系
-
既可以让多个发布者向一个订阅者发布消息,也可以让多个订阅者同时接收一个发布者的消息,核心在于由MQTT Broker负责所有消息路由和分发的工作,用很小的传输消耗和协议数据交换,最大限度减少网络流量。
-
代理(BROKER)能够对消息进行过滤,使每个订阅者只接收自己感兴趣的消息
MQTT主题(TOPIC)
主题(TOPIC)是 MQTT 代理(BROKER)用来识别传送消息的合法客户端的标识符 (ID)。每个想要发送消息的客户端都会在某个主题上发布消息,每个想要接收消息的客户端都会订阅某个主题。
主题是一个字符串,可以由一个或多个主题级别组成。每个级别由正斜杠 (/) 分隔,例如:raspberrypi/model3/sensor/data
一个主题:
-
必须至少有一个字符
-
主题字符串可以包含空格,以允许更具可读性或描述性的主题
-
单独的正斜杠就是一个有效的主题,可用于表示广泛的主题或用作同时订阅多个主题的通配符
-
MQTT主题存在“+”和“#”的通配符,具体可以看下图:
-
区分大小写,比如:raspberrypi/model3/sensor/data和 Raspberrypi/Model3/Sensor/Data是两个不同的主题
比如官网上的一些主题示例:
主题(TOPIC) |
解释 |
---|---|
myhome/groundfloor/livingroom/temperature |
该主题代表位于底层的住宅客厅的温度。 |
SA/California/San Francisco/Silicon Valley |
此主题层次结构可以跟踪或交换有关与美国加利福尼亚州旧金山硅谷地区相关的事件或数据的信息。 |
5ff4a2ce-e485-40f4-826c-b1a5d81be9b6/status |
该主题可用于监视由其唯一标识符标识的特定设备或系统的状态。 |
Germany/Bavaria/car/2382340923453/latitude |
此主题结构可用于共享德国巴伐利亚地区特定汽车的纬度坐标。 |
应用场景
MQTT协议 广泛用于物联网(IoT)、工业物联网 (IIoT) 和机器对机器( M2M )应用。
应用场景 |
示例 |
---|---|
智能家居 |
MQTT 用于连接智能家居中的各种设备,包括智能恒温器、灯泡、安全摄像头和其他电器。这允许用户使用移动应用程序远程控制他们的家庭设备。 |
工业自动化 |
MQTT 用于连接工厂和其他工业环境中的机器和传感器。这样可以实时监控和控制流程,从而提高效率并减少停机时间。温度湿度传感器。 |
农业 |
MQTT 用于精准农业,以监测土壤湿度、天气状况和作物生长。这有助于农民优化灌溉和其他作物管理实践。 |
医疗保健 |
MQTT 用于将医疗设备和传感器(例如血糖仪、心率监视器和血压测量仪等)连接到医疗保健提供者。这样可以对患者进行远程监控,从而改善患者的治疗效果并降低医疗成本。 |
交通 |
MQTT 用于联网汽车和其他交通系统,以实现车辆的实时跟踪和监控。这可以提高安全性并有助于优化交通流量。 |
MQTT消息报文
MQTT 的消息报文类型主要分为 CONNECT 、CONNACK、ONNECT、SUBSCRIBE、SUBACK、UNSUBSCRIBE等
payload其实指的是消息内容(应用程序发布的消息内容),上述报文类型其实是按照:发布者(PUBLISHER)、订阅者(SUBCRIBER)、代理(BROKER),不同角色和请求顺序分的,比如:CONNECT就代表第一次客户端(发布者)向代理(BROKER)发的消息;CONNACK就是第一次收到client消息后,broker返回给client的消息。值得注意的是每一种消息报文类型的payload(消息内容)都不一样。
CONNECT消息
为了初始化连接,需要 client 向 broker 发送 CONNECT 消息。
如果这个 CONNECT 消息格式错误或者打开套接字(因为基于 TCP/IP 协议栈需要初始化 Socket 连接)时间过长,亦或是发送连接消息时间过长的话,broker 就会关闭这条连接
一个 MQTT 客户端发送一条 CONNECT 连接,这条 CONNECT 连接可能会包含下面这些信息:
ClientId |
就是每个客户端的 ID 标识,也就是连接到 MQTT broker 的每个 client。这个 ID 应该是每个 client 和 broker 唯一的 |
CleanSession |
CleanSession 会话标志会告诉 broker client 是否需要建立持久会话。 CleanSession = false:broker 存储 client 的所有订阅以及服务质量(Qos) 是 1 或 2 订阅的 client 的所有丢失的消息 CleanSession = true:broker 则不会为 client 存储任何内容并且会清除先前持久会话中的所有信息 |
Username/Password |
MQTT 会发送 username 和 password 进行 client 认证和授权,PS:如果此信息没有经过加密或者 hash ,那么密码将会以纯文本的形式发送 |
LastWillxxx |
LastWillxxx 表示的是遗愿,client 在连接 broker 的时候将会设立一个遗愿,这个遗愿会保存在 broker 中,当 client 因为非正常原因断开与 broker 的连接时,broker 会将遗愿发送给订阅了这个 topic(订阅遗愿的 topic)的 client。 |
keepAlive |
keepAlive 是 client 在连接建立时与 broker 通信的时间间隔 |
其他类型的相关信息字段的可以参考:https://xie.infoq.cn/article/e345e3a4b3ad74c5893bb8cb8
MQTT协议数据包结构
一个MQTT数据包由:固定头(Fixed header)、可变头(Variable header)、消息体(payload)三部分构成。
-
固定头(Fixed header)。存在于所有MQTT数据包中,表示数据包类型及数据包的分组类标识。
-
可变头(Variable header)。存在于部分MQTT数据包中,数据包类型决定了可变头是否存在及其具体内容。
-
消息体(Payload)。存在于部分MQTT数据包中,表示客户端收到的具体内容。MQTT 是数据无关性的。可以发送任何文本、图像、加密数据以及二进制数据。
MQTT的数据包都包含上述三个部分,每一种消息类型不同的点在于消息体(payload)的不同,例如:
消息类型 |
消息内容 |
---|---|
CONNECT |
消息体内容主要是:客户端的ClientID、订阅的Topic、Message以及用户名和密码 |
SUBSCRIBE |
消息体内容是一系列的要订阅的主题以及QoS |
SUBACK |
消息体内容是服务器对于SUBSCRIBE所申请的主题及QoS进行确认和回复 |
UNSUBSCRIBE |
消息体内容是要订阅的主题 |
MQTT API易受攻击的风险主要来自三个方面:认证/授权缺陷、不安全的传输过程和应用程序本身的安全漏洞,下面我们就从这几个方面来总结出MQTT API到底有哪些攻击风险。
认证/授权缺陷
1.匿名连接登陆/未授权连接
MQTT是允许客户端通过匿名方式连接到消息代理服务器,而无需进行身份验证或提供凭据,这意味着任何人都可以通过简单地建立MQTT连接来访问消息代理,而无需验证自己的身份,任何人都可以通过MQTT API发布或者订阅消息,造成的安全后果可能导致敏感数据泄露或者恶意攻击者发送恶意指令。
对于可能存在该安全风险的MQTT服务,可以通过一些在线的MQTT接入平台进行测试,例如:http://www.emqx.io/online-mqtt-client/
在匿名连接登陆/未授权连接之后,可以通过尝试枚举其他topic来检查是否存在敏感信息。
2.用户密码暴力破解
由于MQTT通过用户名和账号来简单验证登陆,所以在缺乏其他登陆认证机制的情况下,易遭受用户名密码暴力破解攻击,当然这本身和传统的登陆暴力破解没什么区别,并且由于人为疏忽,设置的用户名密码过于简单,恶意攻击者很容易通过常见的MQTT设备弱口令字典成功爆破。
MQTT用户密码暴力破解的工具可以使用mqtt-pwn,https://github.com/akamai-threat-research/mqtt-pwn
爆破的命令如下:
bruteforce --host host --port port -uf USERNAMES_FILE -pf PASSWORDS_FILE
爆破字典存放在mqtt-pwn/resources/wordlists文件夹中。
3.伪冒订阅者/发布者攻击
当我们通过匿名登陆/未授权或者通过暴力破解获取用户名密码连接上了MQTT代理服务器后,由于相关MQTT API权限的控制缺陷,恶意攻击者可以通过MQTT通配符#来冒充订阅者,订阅所有的消息主题
当然,同样是权限控制失效的情况下,恶意攻击者还可以通过冒充合法发布者,发出恶意指令对相对应的订阅者进行恶意控制。
不安全的传输过程
1.从流量中嗅探账户密码
基于TCP协议实现,MQTT协议在流量传输过程中并未采用TLS加密传输,这就导致了恶意攻击者可以通过流量嗅探到用户名密码。当然采用了MQTTS,不存在该风险。
下面是抓取的部分MQTT流量,可以清晰地发现MQTT服务的用户名密码。
在获取用户名密码之后,即可进一步攻击利用。
2.中间人攻击
原因也是由于MQTT协议在流量传输过程中并未使用TLS加密,导致在流量传输过程中,恶意攻击者可以直接在流量中修改发送者发出的消息。这类似于用burpsuite作为中间代理,在客户端和broker之间作为代理,修改传输过程中的消息。
应用程序安全漏洞
1.应用程序自身漏洞
由于MQTT相关应用程序本身代码缺陷导致的相关安全漏洞风险,例如CVE-2017-7296、CVE-2017-7650、CVE-2018-17614、CVE-2019-5432、CVE-2020-13849等等CVE漏洞。
以CVE-2020-13821为例,HiveMQ是企业级MQTT Broker,提供高性能、高可用、高扩展、高安全性的企业级服务,在该漏洞版本存在存储型xss漏洞,下面是漏洞细节:
通过连接工具,在连接配置中的clientid中加入xss 攻击载荷<img/src=x onerror=alert(1)>
返回管理平台,在clients模块,点击Refresh Snaphot触发攻击
Hivemq管理平台成功弹窗
2.管理平台默认口令
除了MQTT应用程序之外,还存在一些管理平台,其中典型的就是EMQX,该项目提供给用户一个可直观查看的web仪表盘,通过web界面可以管理设备与监控设备等等。由于人为疏忽,管理平台可能使用默认密码登陆。
默认密码为:admin/public
其他安全风险
Web应用泄露账号密码
在一些物联网设备中,有的是通过浏览器直接连接到MQTT Broker订阅主题来展示相关信息,这就导致恶意攻击者可以通过javascript文件来找到连接的host、端口、用户名以及密码信息。
下面我们通过几个CVE漏洞的分析来了解一下关于MQTT协议漏洞产生的原理
CVE-2017-7650
该漏洞来源于Mosquitto,这是一个开源的MQTT消息代理(Broker),用于实现MQTT协议。它允许设备和应用在不同的网络之间进行消息传递,从而实现实时通信和数据交换,Mosquitto提供了许多功能,如发布(Publish)和订阅(Subscribe),QoS(Quality of Service)级别控制等。
在 1.4.12 之前的 Mosquitto 中,存在权限绕过漏洞,这允许本地或远程连接的客户端访问他们本无权访问的 MQTT 主题,而Mosquitto 的第三方身份验证/访问控制插件中可能存在同样的问题。
这里介绍下,对于Mosquitto而言,不仅可以使用用户名和密码来限制对于MQTT Broker的访问,还可以通过ACL(也就是访问控制列表)限制对用户对主题的访问,举几个例子
# 赋予user1全部权限
user user1
topic readwrite #
# 允许user2对主题foo/bar/baz的读写权限
user user2
topic foo/bar/#
# 允许 jaythree 读取/写入任何内容
user jaythree
topic #
那么漏洞产生的原因:在上述采用ACL文件来限制用户对主题的访问权限时,如果用户名/客户端 ID 设置为“#”或“+”,那么就可以绕过 ACL的限制。
下面是关于1.4.x版本的修复补丁,明显看到在关于认证权限的相关函数中,添加了对”+”和”#”的检查
CVE-2017-7651
该漏洞也同样是Mosquitto 1.4.14 及之前的所有版本中都存在一个漏洞,这个漏洞的利用是未经身份验证的客户端可以发送精心设计的 CONNECT 数据包,这会导致代理使用大量内存。如果多个客户端执行此操作,则可能会发生内存不足的情况,并且系统可能会变得无响应,或者代理将被操作系统终止。
下面是1.4.15版本的修复补丁,修复的方法是通过限制 CONNECT 数据包允许的大小以及添加memory_limit允许代理自行限制其使用的内存量的配置选项来解决。
结合前面关于MQTT常规的攻击方式,绕过登录权限校验或者嗅探账号密码,这个漏洞利用会显得更加简单。
Portal Lab
星阑科技 Portal Lab 致力于前沿安全技术研究及能力工具化。主要研究方向为API 安全、应用安全、攻防对抗等领域。实验室成员研究成果曾发表于BlackHat、HITB、BlueHat、KCon、XCon等国内外知名安全会议,并多次发布开源安全工具。未来,Portal Lab将继续以开放创新的态度积极投入各类安全技术研究,持续为安全社区及企业级客户提供高质量技术输出。
原文始发于微信公众号(星阑实验室):MQTT协议接口风险解析