# Anesthesia Gateway

| Field | Value |
|-------|-------|
| Category | IoT |
| Difficulty | Medium-Hard |
| Points | 500 |
| 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

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

![mosquitto_sub output listing all discovered topics and their messages](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/mqtt_topics.png)

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](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/mqtt_firmware.png)

### Step 3 — Reverse the encoding chain

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

```python
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](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/mqtt_config_json.png)

### Step 4 — Extract the maintenance key

The decoded JSON contains:

```json
{
    "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

```bash
mosquitto_pub -h <HOST> -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"
```

![flag topic publishing the ESPILON flag after unlock](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/mqtt_flag.png)

### 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}`
