文 年华 | 图 lmn
随着物联网的快速发展,当前在物联网中的常见的五种协议分别是:HTTP、CoAP、XMPP、AMQP、MQTT。但在这么多协议中,毫无疑问MQTT最具代表性,因为它占用带宽小、轻量级、简单易用等优点最符合物联网的应用场景。可以毫不夸张的说:每个物联网开发人员都一定了解MQTT
今天我们将从三个方面来探讨一下MQTT的安全性,分别是登陆认证问题、权限控制问题以及Broker自身安全性的问题(不知道什么是Broker没关系,接着往下看就是了),如果师傅已经了解了MQTT的基础知识建议直接看第三小节
【本文所有截图均在模拟环境进行】
为了防止师傅们疑惑,本文使用术语定义如下:
客户端(Client):使用MQTT的程序或设备,一般分为发布者和订阅者
服务端(Server):发布者和订阅者之间的中介【Broker】
主题(Topic):附加在消息上的一个标签,Broker会将该消息发送给所有订阅该主题的订阅者
主题过滤器(Topic Filter):订阅者订阅时可使用通配符同时订阅一个或多个主题
MQTT的主要工作原理如下图所示,发布者和订阅者就像常见系统中的客户端一样,中心服务器在MQTT中被称为Broker[1]
△ 图片来源:mqtt.org
那MQTT的设计优点有哪些呢?郭朝斌老师将其归纳为五个方面[2]
1. 契合物联网大部分应用场景的发布-订阅模式
2. 能够满足物联网中资源受限设备需要的轻量级特性
3. 时刻关注物联网设备低功耗需求的优化设计
4. 针对物联网中多变的网络环境提供的多种服务质量等级
5. 支持在物联网应用中越来越被重视的数据安全
接下来我们分别讲解一下这五个特性
△ 图片来源:emqx.io
通过上图可以看到有两个MQTT客户端同时订阅了同一个主题Temperature,当温度传感器作为发布者发布其检测到的温度时,订阅者手机、电脑和后端服务器都会收到同样的消息
发布-订阅模式的优点在于发布者与订阅者的解耦,这种解耦表现在以下两个方面[3]:
1. 空间解耦,订阅者与发布者不需要建立直接连接,新的订阅者想要加入网络时不需要修改发布者的行为
2. 时间解耦,订阅者和发布者不需要同时在线,即便不存在订阅者也不影响发布者发布消息
因为发布-订阅模型的应用,使得MQTT允许一个传感器发布的数据触发多个订阅者的一系列动作
MQTT的轻量体现在两个方面:
一是MQTT消息采用二进制的编码格式,充分利用字节位,协议头紧凑,减少了通过网络传输的数据量。下图展示了MQTT的固定头格式:
△ 图片来源:docs.oasis-open.org
二是MQTT消息交互流程非常简单,MQTT 3.1.1一共定义了14种数据包类型,感兴趣的朋友可以查阅MQTT的官方手册,这里不再赘述
https://mcxiaoke.gitbooks.io
MQTT协议十分注重低功耗的优化设计,主要体现在Keepalive机制
这个机制工作的原理是:Client 和 Broker 都基于 Keepalive 确定时间长度,来判断一段时间内是否有消息在双方之间传输。这个时间长度是Client建立连接时设置的,如果超出这个时间长度,双方没有收到新的数据包,那么就判定连接断开。
虽然 Keepalive 要求一段时间内必须有数据包传输,但实际情况是,Client 和 Broker 不可能时刻都在传输主题消息。因此MQTT定义了 PINGREQ 和 PINGRESP 这两种消息类型。它们都没有可变头部和消息体,也就只有 2 个字节大小。Client 和 Broker 通过分别发送 PINGREQ 和 PINGRESP 消息,就能够满足 Keepalive 机制的要求。
此外,MQTT 5.0 还引入了重复主题特性,即Client在重复发送某个Topic的消息时,可以从第二次开始将Topic长度设置为0
在物联网环境中网络质量不稳定、网络带宽低等因素均会影响到发布者、订阅与Broker之间的通信。为了解决这个问题,MQTT协议设计了三种不同的QoS如下:
1. QoS 0,表示消息至多收到一次,即消息可能丢失,但不会重复投递
2. QoS 1,表示消息至少收到一次,即消息保证送达,但可能重复投递
3. QoS 2,表示消息有且只有收到一次
提到安全传输,首先我们要验证客户端是否有权限接入MQTT Broker
MQTT支持两种层次的认证:
1.传输层认证,传输层使用TLS认证设备,并且加密了通讯。
2.应用层认证,支持client id / username / password 等方式认证设备,但是只在应用层验证设备,不加密通讯
在本文中我们主要分析在应用层认证的MQTT,因为在传输层直接使用TLS加密之后我们就没有办法嗅探或者做其他操作了。但也这不是意味着支持TLS就能解决所有问题,因为MCU/RTOS根本玩不了TLS,怎么办?还能怎么办,继续不加密呗
接下来我们再来看看MQTT的认证过程:
客户端将用户名密码使用CONNECT消息发送到Broker,Broker根据认证信息判断是否准入,使用CONNACK消息返回结果,其中认证返回值的具体含义如下:
通过这个表格,其实我们可以判断,如果连接某个Broker,返回值为0就代表我们已经成功连接,如果返回值为4说明我们的账号密码错误,如果返回值为5说明该Broker不支持用户密码方式登陆【需要记住】
最后我们还需要注意Broker支持认证链,它会按照默认先后顺序进行链式认证:
△ 图片来源:docs.emqx.cn
MQTT协议基于主题(Topic)进行消息路由,主题(Topic)类似URL路径,例如:
chat/room/1
主题(Topic)通过'/'分割层级,支持'+', '#'通配符:
'+': 表示通配一个层级,例如a/+,匹配a/x, a/y
订阅者可以订阅含通配符主题,但发布者不允许向含通配符主题发布消息[4]
既然要搞MQTT,怎么可以连工具都没有呢?这里我们直接使用hbmqtt这个库来模拟MQTT client,安装方式很简单,直接pip
pip3 install hbmqtt
这里我们使用eclipse提供的免费broker进行测试,地址如下:
mqtt.eclipseprojects.io
△ 图片来源:mqtt.eclipseprojects.io
它提供了四种mqtt连接方式,今天我们主要来看看不加密的TCP连接方式,即常见的1883端口
我们打开一个终端,订阅/nianhua/iotsecurity这个主题消息:
hbmqtt_sub --url mqtt://mqtt.eclipseprojects.io:1883 -t /nianhua/iotsecurity
打开另一个终端,通过hbmqtt_pub发布一个/nianhua/iotsecurity主题的消息
hbmqtt_pub --url mqtt://mqtt.eclipseprojects.io:1883 -t /nianhua/iotsecurity -m Hello,World!
如果想了解命令的执行细节,可以在上面的命令中加上"-d"参数
再次查看打开的第一个命令行,我们可以发现我们发送的Hello,World!已经接收到了。至此,我们已经完成了一次MQTT通信
另外如果你不喜欢命令行,这里推荐一个超级好用的MQTT客户端:MQTTX 下载地址:https://mqttx.app/cn/
△ 图片来源:mqttx
Emmmmm,如果你连软件都不想下,那这里推荐给你一个在线的MQTT客户端:
tools.exqx.io
△ 图片来源:tools.exqx.io
在这一小节我们主要介绍MQTT面临的安全风险以及如何去攻击
我们可以使用关键字"port=1883 && banner=MQTT"在fofa中搜索使用了默认端口的Broker,搜索结果如下图(January 5, 2021)所示,共发现了约26万可用Broker
△ 图片来源:fofa
接下来我们就从登陆认证问题、权限控制问题以及Broker自身安全性的问题来分析MQTT的安全性
1.匿名登陆
通过使用shodan检索MQTT协议,我们可以发现很多MQTT Connect code为0,这意味着连接到该MQTT Broker无需进行身份验证**【详见1-MQTT简介/安全传输】**
△ 图片来源:shadon
经笔者粗略统计大概有67.9%的可用MQTT Broker设置了匿名登陆:
2.用户名密码暴力破解
说是暴力破解,其实主要还是看字典【主要是MQTT中常见的弱口令】,因为MQTT只是单纯验证用户名和密码,没有其他校验机制,所以我们可以使用暴力破解来尝试获取用户名和密码
借着暴力破解这一小节,我们介绍一个新工具:MQTT-PWN,上图就是我们用MQTT-PWN破解某个MQTT Broker的成功截图,爆破得到了账号密码,就可以直接接入Broker
该项目的Github地址如下:
https://github.com/akamai-threat-research/mqtt-pwn
最好使用Docker的安装方式,pyenv有点问题,暴力破解的命令:
bruteforce --host host --port port -uf USERNAMES_FILE -pf PASSWORDS_FILE
默认用户和密码字典在mqtt-pwn的resources/wordlists文件夹中
MQTT-PWN还支持更多功能,如Owntracks (GPS Tracker)、Sonoff Exploiter等[5]
感兴趣的大家自己看下文档去进行测试
3. 嗅探账号密码
因为MQTT是基于TCP协议实现的,在流量传输的过程中并未考虑加密(这里是指的除去MQTTS之外,即不包含使用TLS的MQTTS),其实这样做也有利于降低客户端设备的成本,毕竟本来单片机算力就不高
假设我们现在和客户端设备位于同一个网络中,我们可以通过嗅探局域网流量(MIMT中间人攻击)来抓取账号密码
△ 图片来源:MQTT安全案例分享[6]
抓取****到设备的账号密码后,我们就可以通过MQTT工具或者是MQTT-PWN连接到Broker进行下一步攻击
4. 从Web应用中获取账号密码
很多厂商为了展示自己的物联网设备,往往会开发一个展示屏幕,如这种:
△ 图片来源:some where
而这些展示的信息来源有部分可能是通过浏览器直接连接到MQTT Broker,订阅部分要展示的信息
通过查看请求信息或者是从F12中的network查看该页面是否有mqtt的连接操作等等,如果有就可以继续在js文件中搜索是否存在mqtt的地址、账号密码等信息
5. 硬件层面-固件提取
对于无法通过一般途径获取账号密码的客户端,我们可以通过提取设备的固件,对其逆向分析,然后把文件系统中的证书或是账号密码****提取出来
然后我们就可以仿冒该设备连接到Broker,订阅/#【主题通配符】。或者是Broker中的ACL配置有问题,尝试是否可以控制其他设备等等
6. 中间人篡改消息
这个中间人和刚刚的账号密码嗅探虽然用的是同一种技术,但是这种方法是直接在流量中修改发送者发出消息
现在攻击者和客户端(发布者/订阅者)在同一个网络中,攻击者作为中间人代理客户端和Broker的通信[4]
假设攻击者想篡改将发布的主题名从"outTpoic"修改为"outTpuc",攻击者需要从流量中筛选出符合条件的报文进行修改,我们可以使用Etterfilter配合脚本来完成:
#owned.filter
1. 登陆至订阅者
当我们通过上述方法登陆至Broker之后,我们可以订阅该broker的所有主题消息(使用/#,#是MQTT消息主题通配符),如下图所示
此外我们还编写了一个脚本用来提取所有发布者发送的消息,我们可以看到提取出来的信息包括姓名、电话、经纬度、昵称以及其他敏感信息等等【实验数据!!!】
2. 登陆至发布者
我们还可以对该系统中的主题进行分析,这里我们以路灯举例,路灯作为订阅者接收来自合法发布者的控制。如下图所示,如果我们冒充合法发布者对路灯进行恶意控制
此外,我们还可以冒充发布者发布****更新固件指令,blah ... 下面我们来看个案例[6]
智慧大厦场景中存在和停车、安防、灯光、广播、会议、环境监测等相关的各类传感器,这些传感器将受控于网关,并利用网关将数据传输到云端呈现。在本案例中,MQTT的通信安全问题出现在智慧大厦的网关盒子中。
拓扑逻辑如下:
在MQTT的通信场景中,研究员在网关前端抓取TCP数据包,并通过盒子的平台控制盒子的Wi-Fi射频打开与关闭,发现其通信方式使用的是MQTT通信,其认证方式只用了用户名和密码。
基于之前的分析,发现只需要一条shell命令即可控制这个通信过程。事实证明,盒子的Wi-Fi指示灯成功被我们熄灭和点亮。
由于存在厂商相关的敏感信息,本章不再展示实图,有兴趣的朋友欢迎随时沟通交流。
1. 默认账户口令
现在有很多开源的Broker实现,在国内较为出名的是EMQ X,它不仅提供高并发能力的集群特性还支持扩展插件机制。该项目还提供给用户一个可直观查看的web仪表盘,通过web界面可以管理设备与监控设备等等。
但该项目为了方便使用者,直接为web管理台设置了默认账号密码,很多厂商部署了EMQ X之后并不会修改默认账号密码,如下图:
通过shadon我们检索出18083端口且title中包含Dashboard的站点,可以使用默认口令尝试登陆**【我没试!!!!!!求生欲强烈!!!】**
2. XSS漏洞
现在很多Broker都支持WEB端管理,管理员可以直接通过浏览器查看client以及topic等信息。如果我们使用mqtt直接发送包含有xss的信息到Broker就可以直接绕过web端的防御
这里我们使用CVE-2020-13821做实验,首先本地搭建一个hivemq 4.3.2:
docker run -p 8080:8080 -p 1883:1883 hivemq/hivemq4:4.3.2
该Broker的用户名和密码为admin和hivemq,如下图所示:
我们使用hbmqq来发布一个消息,其中消息的内容随便输入,指定client-id为xss payload:
hbmqtt_pub --url mqtt://ip:port -t / -m 1 -i "<img src=x onerror=prompt(2);>"
再回到HiveMQ中的Clients功能页,点击Refresh Snapshot刷新所有MQTT会话:
Bingo,这里只是弹窗演示一下,实际攻击环境中可以更换为XSS平台的payload
3. 其他漏洞
现在MQTT Broker供应商越来越多,但是经过这几天的检索,发现漏洞其实并没有想象的那么多。但是很多攻击面是可以预见的,像是发布者发送消息到订阅者,Broker有可能将其存入数据库,如果没有做好转义,是否能够产生注入等等
这里也仅仅是提供一下思路,希望能够达到抛砖引玉的效果,如果师傅们发现什么好玩的漏洞,欢迎来《物联网IoT安全》公众号投稿
4 其他
MQTT在僵尸网络中应用这一思路最早是由Lucas和Neal在DEFCON24上提出[7],如下图所示
被控IoT设备即是发布者也是订阅者,僵尸设备发布关于设备自身运行状态到bot/status主题,同时订阅用于执行命令的bot/command主题
而C&C攻击者可以通过bot/command主题向设备发送指令,通过订阅bot/status主题获取每个设备的运行状态
5 防范措施
1. 使用MQTTS防止中间人攻击
2. 在MQTT Broker上启用Topic ACL
3. 尽量使用客户端证书作为设备身份凭证,以验证设备合法性
总之,MQTT协议在安全上做出了很多努力,但是使用者并不在意这些安全特性,可能是受限于硬件资源或是对于安全的不重视
如果想要了解更多MQTT的安全防范机制,可以访问
https://www.hivemq.com/mqtt-security-fundamentals/
以获得帮助
6 TODO
最近一直在使用MQTT-PWN,但感觉不是特别好用。希望有时间LMN师傅可以开发一个MQTT的漏洞利用套件**【MQTT-SUIT】**
7 参考引用
[1] MQTT: The Standard for IoT Messaging. Retrieved January 7, 2021, from https://mqtt.org/
[
Cobalt Strike|DNS Beacon
广告时间