Skip to content
HackIndex logo

HackIndex

Tools

Flask Cookie Forge & Decoder

Decode Flask itsdangerous session cookies or forge signed ones — for CTF challenges and authorised testing.

Flask signs session cookies using the itsdangerous library with HMAC-SHA1 or HMAC-SHA512. The cookie format is PAYLOAD.TIMESTAMP.SIGNATURE — all segments are base64url-encoded. Compressed payloads start with a dot prefix. This tool decodes any Flask session cookie to reveal the JSON payload (no key required), verifies the HMAC signature when you provide the SECRET_KEY, and lets you forge a new valid signed cookie. All processing happens server-side in PHP. Nothing is stored or logged.

Decode Cookie

Decode & verify an existing Flask cookie

Found in target app config as SECRET_KEY. Used to verify the HMAC signature.

Flask-Session uses "cookie-session" by default. Only change if the target app uses a custom salt.

Forge Cookie

Generate a valid signed Flask cookie

Flask uses HMAC-SHA1 by default. Some apps configure HMAC-SHA512.

Leave blank for Flask default "cookie-session".

Tip: decode a real cookie first to see the exact JSON structure, then modify and forge.

How 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. 1. Get the cookie: intercept the target request in Burp Suite or browser DevTools and copy the session cookie value.
  2. 2. Decode: paste the cookie to reveal the JSON payload without needing a key — Flask cookies are signed, not encrypted.
  3. 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. 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. 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").