$ cat writeup.md…
$ cat writeup.md…
umdctf
Task: an internal HTTPS service exposed login and dashboard endpoints, while an admin box repeatedly queried the server from the same LAN. Solution: instead of exploiting the visible BREACH-style compression oracle, ARP-spoof the admin and abuse disabled TLS verification to steal credentials and read the flag.
$ cat /etc/rate-limit
Rate limit reached (20 reads/hour per IP). Showing preview only — full content returns at the next hour roll-over.
Our agents have infiltrated the world's smallest--I mean largest--insider trading network! They left a note for you on the server. Best of luck!
The challenge provided a shell via nc challs.umdctf.io 31337, plus the admin.py and server.py sources. The note explained that the player host was inside the same small internal network as an admin box and the HTTPS server, and that the flag format was UMDCTF{[a-z0-9_]+}.
The first obvious bug was a BREACH-style compression oracle. The admin continuously requested /api/dashboard, and that JSON response contained both attacker-controlled input and the secret flag:
{"filter":"...user-controlled...","flag":"UMDCTF{...}"}
Because the admin advertised compression support (Accept-Encoding: gzip, deflate, br, zstd) and polled roughly every 50 ms, it looked like the intended route was to manipulate filter, observe compressed lengths, and recover the flag one character at a time.
But the much shorter path was in admin.py. The admin HTTPS client explicitly disabled TLS validation:
ctx = ssl.create_default_context() ctx.check_hostname = False ctx.verify_mode = ssl.CERT_NONE
That turns HTTPS into encryption without authentication. Any host that can place itself in the middle and present any certificate at all can impersonate the server.
The network layout from the note and runtime behavior was:
10.0.0.1 — admin box10.0.0.2 — real HTTPS server10.0.0.3 — player shellThe player shell also had exactly the capabilities needed for a LAN MITM: arpspoof, tcpdump, curl, openssl, python3, plus cap_net_admin and cap_net_raw.
The provided server.py behavior mattered mainly for the endpoint map:
POST /login POST /api/suggestions GET /api/suggestions/latest GET /api/dashboard
...
$ grep --similar