Flash
Writeup for Flash (Web) - Tsuku CTF (2025) π
Description
3, 2, 1, pop!
Solution
Site functionality
When we open the website, we are welcomed to a basic page that says Flash! and presents a start button. Clicking start will cycle through 10 rounds, displaying a 7 digit unique number each time.
When we get to the end, we have to enter the total value.
I thought maybe I could just use a match/replace rule in burp to change the timeout of each round from 500ms to 5000ms, giving me time to write down each number. However, some of the rounds (4-7) don't show any value at all.
Note that each round provides a new session cookie, which we can decode with flask-unsign.
Source code
The challenge comes with source code, app.py is the most interesting.
Breaking it down
The Flask app generates a series of 10 pseudo-random 7-digit numbers using a deterministic PRNG seeded by a secret value and a session ID. The goal is to calculate the sum of all 10 numbers, but only rounds 1β3 and 8β10 are visible.
At startup, the app reads a secret SEED from ./static/seed.txt. This file is served from Flask's static/ directory, making it publicly downloadable.
When we visit /, the app generates a new session with a random session_id and sets the round to 0. The session_id is stored in the Flask session cookie, which is signed but decodable (using flask-unsign).
Each round's number is generated by a linear congruential generator (LCG), with parameters (a, c) and initial state derived from HMACs of the SEED and session_id. The generator advances the state based on the current round index and produces 7 digits per round.
The /flash endpoint shows the digits in an image if the round is in [0, 1, 2, 7, 8, 9]; otherwise, the digits are hidden. It progresses through the rounds automatically, and after round 10, we are redirected to /result.
At /result, we must submit the sum of all 10 numbers. The server recomputes all 10 numbers using the stored session_id and compares the submitted sum to the correct one. If the answer is correct, the flag is displayed.
Steps to solve:
Download
seed.txtfrom/static/seed.txt.Go through all 10 rounds in a single session, preserving the session cookie.
Decode the
session_idfrom the cookie after the 10 rounds.Use the known
SEEDand decodedsession_idto regenerate all 10 numbers using the PRNG logic.Compute the sum and submit it at
/resultto receive the flag.
We can use ChatGPT to make a quick solve script π
solve.py
We run the script, and receive the flag π€€
Not sure if I took the intended approach here, since I didn't actually do any path traversal. I feel like I was tricked into doing a crypto challenge π
Flag: TsukuCTF25{Tr4d1on4l_P4th_Trav3rs4l}
Last updated
