Rush Hour
Challenge
A notes app with an admin bot. The injection point was the note body at /create?note=, but two things made it hard: each note was length restricted, and the page shipped a brutal CSP that killed inline scripts and external loads. We took first blood on it.
Approach
Three problems, three tricks:
1. Beating the length limit with comment stitching. A single note was too short to hold the payload, but you can spread one script across several injected notes and use multiline JS comments (/* ... */) to swallow the page markup in between. Open three notes whose fragments concatenate, in the rendered DOM, into one valid script:
/create?note=<script>location=/*
/create?note=*/localStorage.getItem("a");/*
/create?note=*/</script>
Everything the app renders between those fragments lands inside a /* */ comment, so the browser sees one clean script.
2. Beating the CSP with navigation. The CSP blocked the usual exfil channels, so instead of fetching, the payload drives the page with window.location / window.open to navigate the bot where we need it.
3. Getting the flag cookie set. The flag isn’t readable from the injection page; the admin bot only gets the supersecretstring cookie once it visits its own user page. The script keys off the admin’s user cookie being 42 characters, poisons the admin’s notes with the secondary payload, navigates the bot to /user/<its-id> so the cookie is set, then the secondary injection fires and redirects to our webhook with the flag.
The working payload:
| |
The flag landed on our webhook. Shortly after first blood the organizers dropped a v2 of the challenge; the only real change was the exfil channel, so swapping window.location for window.open on the final hop solved that one too.