write-up: IoT/Observe_The_Wired/README.md
This commit is contained in:
parent
30bd8dfd02
commit
9844d09683
@ -1,52 +1,154 @@
|
|||||||
# Observe The Wired -- Solution
|
# Observe The Wired
|
||||||
|
|
||||||
## Overview
|
| Field | Value |
|
||||||
CoAP node with observable stream. Recover fragments, decode the firmware blob, then POST the maintenance key.
|
|-------|-------|
|
||||||
|
| Category | IoT |
|
||||||
|
| Difficulty | Medium-Hard |
|
||||||
|
| Points | — |
|
||||||
|
| Author | Eun0us |
|
||||||
|
| CTF | Espilon 2026 |
|
||||||
|
|
||||||
## Steps
|
---
|
||||||
|
|
||||||
|
## Description
|
||||||
|
|
||||||
|
An IoT module from Clinique Sainte-Mika (Room 013) communicates via **CoAP** on the
|
||||||
|
WIRED-MED network. The stream seems stable... but the observation layer hides a key fragment.
|
||||||
|
|
||||||
|
*In The Wired, only observers hear the truth.*
|
||||||
|
|
||||||
|
Explore the CoAP resources, observe the stream, reconstruct the key, decode the firmware
|
||||||
|
blob, and open the maintenance channel.
|
||||||
|
|
||||||
|
- CoAP: `udp/<host>:5683`
|
||||||
|
|
||||||
|
Format: **ESPILON{flag}**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## TL;DR
|
||||||
|
|
||||||
|
Discover CoAP resources with a `.well-known/core` GET. Collect fragments A, B, C from
|
||||||
|
`/status`, `/telemetry/heart`, and the observable `/wired/stream`. Concatenate to build
|
||||||
|
XOR key `WIREDLAIN23`. Download and decode the firmware blob from `/archive/firmware`.
|
||||||
|
POST the maintenance key `0BS3RV3-L41N-23` to unlock and get the flag.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Tools
|
||||||
|
|
||||||
|
| Tool | Purpose |
|
||||||
|
|------|---------|
|
||||||
|
| `coap-client` (libcoap) | CoAP GET, observe, POST |
|
||||||
|
| Python 3 | XOR decode, base64 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Solution
|
||||||
|
|
||||||
|
### Step 1 — Discover resources
|
||||||
|
|
||||||
1. Discover resources
|
|
||||||
```bash
|
```bash
|
||||||
coap-client -m get coap://HOST/.well-known/core
|
coap-client -m get coap://<HOST>/.well-known/core
|
||||||
```
|
```
|
||||||
|
|
||||||
2. Get fragments A and B
|
Returns a comma-separated list of resource links (RFC 6690 format):
|
||||||
```bash
|
|
||||||
coap-client -m get coap://HOST/status
|
```
|
||||||
coap-client -m get coap://HOST/telemetry/heart
|
</status>,</telemetry/heart>,</telemetry/temp>,
|
||||||
|
</wired/stream>;obs,</archive/firmware>,
|
||||||
|
</maintenance/unlock>
|
||||||
```
|
```
|
||||||
|
|
||||||
3. Observe the stream for fragment C
|
> 📸 `[screenshot: .well-known/core response listing all CoAP resources]`
|
||||||
```bash
|
|
||||||
coap-client -m get -s 30 -o coap://HOST/wired/stream
|
### Step 2 — Get fragment A
|
||||||
```
|
|
||||||
Capture the JSON notification that includes `fragment_c`.
|
```bash
|
||||||
|
coap-client -m get coap://<HOST>/status
|
||||||
|
```
|
||||||
|
|
||||||
|
Response includes: `fragment_a: WIRED`
|
||||||
|
|
||||||
|
### Step 3 — Get fragment B
|
||||||
|
|
||||||
|
```bash
|
||||||
|
coap-client -m get coap://<HOST>/telemetry/heart
|
||||||
|
```
|
||||||
|
|
||||||
|
Response includes: `fragment_b: LAIN`
|
||||||
|
|
||||||
|
### Step 4 — Observe the stream for fragment C
|
||||||
|
|
||||||
|
Subscribe to the observable resource for 30 seconds:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
coap-client -m get -s 30 -o observe_out.txt coap://<HOST>/wired/stream
|
||||||
|
```
|
||||||
|
|
||||||
|
Among the periodic notifications, one JSON payload contains:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{"fragment_c": "23", "node": "013"}
|
||||||
|
```
|
||||||
|
|
||||||
|
> 📸 `[screenshot: observable stream notification containing fragment_c value]`
|
||||||
|
|
||||||
|
### Step 5 — Build the XOR key
|
||||||
|
|
||||||
4. Build XOR key
|
|
||||||
Concatenate fragments in order A + B + C:
|
Concatenate fragments in order A + B + C:
|
||||||
|
|
||||||
```
|
```
|
||||||
WIRED + LAIN + 23 = WIREDLAIN23
|
WIRED + LAIN + 23 = WIREDLAIN23
|
||||||
```
|
```
|
||||||
|
|
||||||
5. Download firmware blob
|
### Step 6 — Download and decode the firmware blob
|
||||||
```bash
|
|
||||||
coap-client -m get coap://HOST/archive/firmware
|
|
||||||
```
|
|
||||||
Save the base64 data between `FIRMWARE_B64_BEGIN` and `FIRMWARE_B64_END` into `firmware.b64`.
|
|
||||||
|
|
||||||
6. Decode the blob
|
|
||||||
```bash
|
```bash
|
||||||
python3 decode.py firmware.b64
|
coap-client -m get coap://<HOST>/archive/firmware
|
||||||
```
|
```
|
||||||
The JSON includes `maintenance_key`.
|
|
||||||
|
|
||||||
7. Unlock and get the flag
|
The response is a text payload with base64 between markers:
|
||||||
```bash
|
|
||||||
coap-client -m post -e '0BS3RV3-L41N-23' coap://HOST/maintenance/unlock
|
|
||||||
```
|
```
|
||||||
|
FIRMWARE_B64_BEGIN
|
||||||
|
<base64 data>
|
||||||
|
FIRMWARE_B64_END
|
||||||
|
```
|
||||||
|
|
||||||
|
Save and decode:
|
||||||
|
|
||||||
|
```python
|
||||||
|
import base64, json
|
||||||
|
|
||||||
|
with open("firmware.b64") as f:
|
||||||
|
b64_data = f.read().strip()
|
||||||
|
|
||||||
|
raw = base64.b64decode(b64_data)
|
||||||
|
|
||||||
|
# XOR with key WIREDLAIN23
|
||||||
|
key = b"WIREDLAIN23"
|
||||||
|
decoded = bytes(b ^ key[i % len(key)] for i, b in enumerate(raw))
|
||||||
|
|
||||||
|
config = json.loads(decoded.decode())
|
||||||
|
print(config["maintenance_key"])
|
||||||
|
# 0BS3RV3-L41N-23
|
||||||
|
```
|
||||||
|
|
||||||
|
> 📸 `[screenshot: Python script printing the maintenance key from the decoded firmware blob]`
|
||||||
|
|
||||||
|
### Step 7 — Unlock and get the flag
|
||||||
|
|
||||||
|
```bash
|
||||||
|
coap-client -m post -e "0BS3RV3-L41N-23" coap://<HOST>/maintenance/unlock
|
||||||
|
```
|
||||||
|
|
||||||
|
The response contains the flag.
|
||||||
|
|
||||||
|
> 📸 `[screenshot: CoAP POST response returning the flag]`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Flag
|
## Flag
|
||||||
`ESPILON{c0ap_0bs3rv3_th3_w1r3d}`
|
|
||||||
|
|
||||||
## Author
|
`ESPILON{c0ap_0bs3rv3_th3_w1r3d}`
|
||||||
Eun0us
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user