ESPILON-CTF-2026-Writeups/IoT/Anesthesia_Gateway/README.md
Eun0us 6a0877384d [+] Writeups v2 — sync solves, real points, scoreboard stats, cleanup
- Remove undeployed challenges: Phantom_Byte, Cr4cK_w1f1, Lain_Br34kC0r3 V1,
  Lain_VS_Knights, Lets_All_Love_UART, AETHER_NET, Last_Train_451, Web3/
- Sync 24 solve/ files from main CTF-Espilon repo
- Update all READMEs with real CTFd final scores at freeze
- Add git-header.png banner
- Rewrite README: scoreboard top 10, edition stats (1410 users, 264 boards,
  1344 solves), correct freeze date March 26 2026
2026-03-27 21:27:45 +01:00

3.8 KiB

Anesthesia Gateway

Field Value
Category IoT
Difficulty Medium-Hard
Points 495
Author Eun0us
CTF Espilon 2026

Description

The anesthesia monitoring gateway in Operating Room 13 at Clinique Sainte-Mika is broadcasting live data over MQTT.

Something unusual is being transmitted on the network. The contractor left a debug channel open.

Connect to the MQTT broker and investigate.

  • MQTT Broker: tcp/<host>:1883

Format: ESPILON{flag}


TL;DR

Subscribe to the MQTT wildcard topic sainte-mika/#. Find the debug firmware topic publishing a base64-encoded blob every 45 seconds. Reverse the encoding chain (base64 → XOR with key WIRED → zlib decompress → JSON) to extract the maintenance key N4V1-C4R3-0R13-L41N. Publish it to the unlock topic to receive the flag.


Tools

Tool Purpose
mosquitto_sub / mosquitto_pub MQTT client
Python 3 Decode base64, XOR, zlib, JSON

Solution

Step 1 — Connect and discover topics

mosquitto_sub -h <HOST> -t "sainte-mika/#" -v

mosquitto_sub output listing all discovered topics and their messages

Topics discovered:

Topic Content
sainte-mika/or13/vitals Patient vital signs (JSON)
sainte-mika/or13/sevoflurane Anesthetic gas data
sainte-mika/or13/propofol Infusion pump data
sainte-mika/or13/ventilator Ventilator data
sainte-mika/or13/alarms Alarm status — note "network": "WIRED-MED"
sainte-mika/or13/debug/firmware Base64 blob, published every 45s

Step 2 — Capture the firmware blob

Wait for a message on debug/firmware (up to 45 seconds). Save the base64 string.

Note the "network": "WIRED-MED" in the alarms topic — this is the XOR key hint.

debug/firmware topic publishing the base64-encoded blob

Step 3 — Reverse the encoding chain

The chain is: base64 → XOR("WIRED") → zlib → JSON

import base64, zlib, json

blob = "<base64 string from debug/firmware>"

# Step 1: base64 decode
raw = base64.b64decode(blob)

# Step 2: XOR with key "WIRED"
key = b"WIRED"
xored = bytes(b ^ key[i % len(key)] for i, b in enumerate(raw))

# Verify: first two bytes after XOR should be 0x78 0x9C (zlib magic)
assert xored[:2] == b'\x78\x9C', "Key is wrong — magic bytes don't match"

# Step 3: zlib decompress
decompressed = zlib.decompress(xored)

# Step 4: parse JSON
config = json.loads(decompressed.decode())
print(config)

Python script printing the decoded JSON configuration

Step 4 — Extract the maintenance key

The decoded JSON contains:

{
    "maintenance_key": "N4V1-C4R3-0R13-L41N"
}

The key is a leetspeak encoding of "Navi Care OR13 Lain".

Step 5 — Publish the key and get the flag

mosquitto_pub -h <HOST> -t "sainte-mika/or13/maintenance/unlock" -m "N4V1-C4R3-0R13-L41N"

Subscribe to the flag topic:

mosquitto_sub -h <HOST> -t "sainte-mika/or13/maintenance/flag"

flag topic publishing the ESPILON flag after unlock

Key insights

  • The XOR key WIRED is derivable from the alarms topic which includes "network": "WIRED-MED"
  • After XOR decryption, the zlib magic bytes 0x78 0x9C confirm the correct key
  • MQTT wildcard subscription # enumerates all topics in one command
  • An open MQTT broker with no authentication is a real-world IoT misconfiguration

Flag

ESPILON{mQtt_g4tw4y_4n3sth3s14}