Flask Cookie Forge & Decoder
Decode Flask itsdangerous session cookies or forge signed ones — for CTF challenges and authorised testing.
Decode Cookie
Decode & verify an existing Flask cookieForge Cookie
Generate a valid signed Flask cookieHow it works
Flask uses the itsdangerous library to sign session cookies with HMAC. The cookie format is three base64url segments separated by dots: PAYLOAD.TIMESTAMP.SIGNATURE. The key derivation is HMAC-{algo}(key=secret, msg=salt) — the derived key is then used to compute HMAC-{algo}(key=derived, msg=PAYLOAD.TIMESTAMP). This tool decodes and optionally verifies any Flask session cookie, then lets you forge a new one — all server-side in PHP without storing any input.
- 1. Get the cookie: intercept the target request in Burp Suite or browser DevTools and copy the session cookie value.
- 2. Decode: paste the cookie to reveal the JSON payload without needing a key — Flask cookies are signed, not encrypted.
- 3. Get the SECRET_KEY: find it in the target app config, a leaked .env, git history, or crack it from the known signature.
- 4. Modify & forge: change the JSON payload (e.g. set user_id or is_admin), enter the SECRET_KEY and forge a new valid signed cookie.
- 5. Inject: replace the session cookie in your request and resend.
What are Flask session cookies?
Flask stores the entire session dictionary directly in the browser cookie — there is no server-side session store by default. The session object is JSON-serialized, optionally zlib-compressed, base64url-encoded, and signed with HMAC using the app's SECRET_KEY. The signature prevents tampering, but because the payload is not encrypted, anyone can read the session data without the key. This makes Flask session cookies a common target in CTF web challenges.
payload
Base64url-encoded JSON object (zlib-compressed if prefixed with a dot). Contains the session data — user_id, roles, CSRF token, etc.
timestamp
4-byte big-endian Unix epoch packed into base64url. Present in timed cookies (URLSafeTimedSerializer). Used for cookie expiry checks.
signature
base64url(HMAC-{algo}(derived_key, PAYLOAD.TIMESTAMP)). Derived key = HMAC-{algo}(secret_key, salt). Default salt is "cookie-session".
compression
itsdangerous compresses the payload with zlib deflate when compression saves space. Compressed payloads are prefixed with a dot before base64url encoding.
FAQ
Does this send my cookie or SECRET_KEY anywhere?
No. All decoding and signing happens server-side in PHP. No data is stored, logged, or transmitted to third parties.
Can I read the payload without the SECRET_KEY?
Yes — Flask cookies are signed but not encrypted. Paste the cookie without a key to instantly see the JSON session data. You only need the SECRET_KEY to verify or forge a valid signature.
How does the itsdangerous key derivation work?
itsdangerous derives a signing key as HMAC-{algo}(key=secret_key, msg=salt). The signature is then HMAC-{algo}(key=derived_key, msg=PAYLOAD.TIMESTAMP). This differs from a direct HMAC — the salt adds domain separation between different uses of the same secret key.
What algorithm should I choose when forging?
HMAC-SHA1 is the Flask/itsdangerous default. Use HMAC-SHA512 only if the target app explicitly configures it. You can detect the algorithm by trying both during decode — this tool tries sha1 first, then sha512.
Decoding fails or signature is invalid — why?
Ensure you paste the raw cookie value without URL-encoding (%3D etc). The tool handles URL-encoded input automatically. For signature verification, check the SECRET_KEY is correct and the salt matches the target app (default is "cookie-session").