# Findings — Brunnerne 2026 A/D ## arena-battle (pwn, port 1337->31337) Status: partially patched (see services/arena-battle/PATCH_NOTES.md items 1-7). Sploit: challenges/pwn/arena-battle/work/sploit.py (+predictors.py) — token prediction via unsalted glibc rand(); verified 15/15 flags vs vulnerable build. ### Remaining holes in OUR patched server (audit 2026-08-26) - [P1] NOTE_CREATE lines logged verbatim to logs/server.log -> any file-read anywhere on box = flag dump. Fix: redact. - [P2] SLA: ATTACK ignores current_turn; anyone can FIGHT+ATTACK our checker's fighter to hp=0 (dead forever until 1h cleanup) + steal gold. Fix: auto-revive dead fighters after ~60s. - [P3] Memory DoS: battles map never erased, b.logs unbounded, inventory push_back loop bounded only by gold. Fix: caps + GC of ended battles. - [P4] LOGOUT leaves fighter_battle entry (teardown skips because client_fighter already erased) -> ghost-battle desync. Fix: logout ends battle. - [P5] write() not looped -> partial-write truncation on big NOTE listings. - Cleanup thread erases fighter_battle[fid] for OLD inactive battle even if fid is now in a NEWER active battle (minor desync, low prio). ### Offense roadmap (vs other teams' half-fixes) - default-seed rand(): DONE (glibc+darwin predictors). - srand(time(NULL)): TODO — brute-force seed from 1-2 self-registered tokens. - std::mt19937(time) / fixed seed: TODO — own mt19937 impl + state recovery from tokens we harvest by registering (REGISTER echoes TOKEN). - NOTE_GET has no rate limit across reconnects (MAX_BAD_TOKENS is per-conn). ### Verified facts - work/server.cpp == services_vulnerable/arena-battle/server.cpp (diff clean). - Flag format [A-Z0-9]{31}= ; store = fighter notes; NOTE_GET auths on token alone. - checker_sim.py: REGISTER CheckerX warrior + NOTE_CREATE . ## Other services (not started) - rusgram, tiktak, "services 4" — pending triage.