diff --git a/IoT/Anesthesia_Gateway/README.md b/IoT/Anesthesia_Gateway/README.md index 7da59e5..7f04189 100644 --- a/IoT/Anesthesia_Gateway/README.md +++ b/IoT/Anesthesia_Gateway/README.md @@ -1,72 +1,142 @@ -# Anesthesia Gateway -- Solution +# Anesthesia Gateway -## Overview -MQTT broker simulating an anesthesia monitoring gateway. A debug topic leaks -an encoded firmware blob. Reverse the encoding to extract a maintenance key -and publish it to unlock the flag. +| Field | Value | +|-------|-------| +| Category | IoT | +| Difficulty | Medium-Hard | +| Points | 500 | +| Author | Eun0us | +| CTF | Espilon 2026 | -## Steps +--- + +## 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/: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 -### 1. Connect and discover topics ```bash -mosquitto_sub -h HOST -t "sainte-mika/#" -v +mosquitto_sub -h -t "sainte-mika/#" -v ``` +> 📸 `[screenshot: mosquitto_sub output listing all discovered topics and their messages]` + Topics discovered: -- `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` -- mechanical ventilator data -- `sainte-mika/or13/alarms` -- alarm status (note: `"network": "WIRED-MED"`) -- `sainte-mika/or13/debug/firmware` -- **base64-encoded blob (every 45s)** -### 2. Capture firmware blob -Grab the base64 string from `debug/firmware`. +| 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** | -### 3. Decode the blob -The encoding chain is: JSON -> zlib -> XOR("WIRED") -> base64 +### 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. + +> 📸 `[screenshot: debug/firmware topic publishing the base64-encoded blob]` + +### Step 3 — Reverse the encoding chain + +The chain is: `base64 → XOR("WIRED") → zlib → JSON` -To reverse: ```python -import base64, zlib +import base64, zlib, json -blob = "" +blob = "" + +# Step 1: base64 decode raw = base64.b64decode(blob) -# XOR with key "WIRED" (hint: WIRED-MED appears in alarm data) +# Step 2: XOR with key "WIRED" key = b"WIRED" xored = bytes(b ^ key[i % len(key)] for i, b in enumerate(raw)) -# After XOR, bytes start with 78 9C (zlib magic) -config = zlib.decompress(xored) -print(config.decode()) +# 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) ``` -### 4. Extract maintenance key +> 📸 `[screenshot: Python script printing the decoded JSON configuration]` + +### Step 4 — Extract the maintenance key + The decoded JSON contains: + ```json { "maintenance_key": "N4V1-C4R3-0R13-L41N" } ``` -### 5. Publish key and get flag +The key is a leetspeak encoding of "Navi Care OR13 Lain". + +### Step 5 — Publish the key and get the flag + ```bash -mosquitto_pub -h HOST -t "sainte-mika/or13/maintenance/unlock" -m "N4V1-C4R3-0R13-L41N" +mosquitto_pub -h -t "sainte-mika/or13/maintenance/unlock" -m "N4V1-C4R3-0R13-L41N" ``` Subscribe to the flag topic: + ```bash -mosquitto_sub -h HOST -t "sainte-mika/or13/maintenance/flag" +mosquitto_sub -h -t "sainte-mika/or13/maintenance/flag" ``` +> 📸 `[screenshot: flag topic publishing the ESPILON flag after unlock]` + ### Key insights -- The XOR key "WIRED" is discoverable from the alarm topic which includes `"network": "WIRED-MED"` -- After XOR decryption, the zlib magic bytes `78 9C` confirm the correct key -- The maintenance key "N4V1-C4R3-0R13-L41N" = "Navi Care OR13 Lain" in leetspeak + +- 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}` -## Author -Eun0us +`ESPILON{mQtt_g4tw4y_4n3sth3s14}`