[Tools](https://hackindex.io/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

## Forge Cookie

Generate a valid signed Flask cookie

## 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").
