Private Beta
.md

BountyHub Docs

Cookie Lab

Decode and unsign vulnerable stateless session cookies with Cookie Lab, entirely in your browser.

Cookie Lab

The Cookie Lab decodes and unsigns vulnerable stateless session cookies using a native Rust port of CookieMonster. Crack a single cookie in your browser — the cookie and any wordlist you load never leave the page — or queue a batch across your runners.

#What it detects

Cookie Lab decodes cookies from several frameworks and then tries to recover the signing key from a wordlist:

  • Django
  • Flask and itsdangerous
  • Rack
  • Express (cookie-session)
  • Laravel
  • CodeIgniter
  • WordPress authentication cookies
  • Yii2 signed cookies
  • Spring Security remember-me cookies
  • raw JSON Web Tokens (HS256/HS384/HS512)

A recovered key means the target signs sessions with a guessable secret, so an attacker can forge a session and impersonate any user. Report the finding and ask the owner to rotate the signing secret.

Pick a Cookie type to force one framework, or leave it on Auto-detect. As you paste a cookie, Cookie Lab parses it locally and shows the formats that understand it, the signing algorithm it implies, and the decoded payload — no wordlist needed. If you force a type that does not match, the lab warns you and suggests switching back to Auto-detect.

The selected type is recorded with each run (for example decoder=flask,jwt), so the backlog shows what a run was testing instead of an opaque "auto".

#Using the lab

  1. Open Cookie Lab.
  2. Paste the session cookie you are authorized to test. For Express cookie-session, use the name=value^signature form. Pasting a whole Set-Cookie header is fine — a strip attributes shortcut keeps just the cookie value.
  3. Choose a wordlist. A wordlist is required — Cookie Lab bundles no default list. Auto-detect reads either a plain-text list (one key per line) or a base64 (Flask-Unsign) list; you can force the format instead. Uploading or pasting both work, and the lab shows the detected format, entry count, and a preview. For WordPress and Spring Security the entry format differs; see below.
  4. Click Decode & crack.

#WordPress and Spring Security wordlist entries

Most frameworks use the wordlist entry directly as the signing secret. Two frameworks derive the signature from material that is not stored in the cookie:

  • WordPress derives its HMAC key from the scheme salt (AUTH_KEY + AUTH_SALT, or the LOGGED_IN_/SECURE_AUTH_ pair) and a four-character fragment of the user's password hash. Use salt:pass_frag as the entry, or the already derived wp_hash() key. The entry is split on the last colon because WordPress salts may contain colons.
  • Spring Security remember-me tokens sign username:expiry:password:key. Use the combined password:key suffix as the entry; the password is usually the stored hash Spring sees.

If a key is recovered, the result shows the matching decoder(s), the algorithm, the decoded payload, and the key. The optional Resign field re-signs a decoded Django or Flask cookie with new content. A few example cookies are built in so you can try the lab before pointing it at a target.

#Local vs runner

The lab has two backends:

  • In your browser cracks a single cookie instantly using the Cookie Lab WebAssembly build. The cookie never leaves the browser. Cracking is single-threaded, so large wordlists are capped at 10 MB.
  • On your runners is a queue. Paste one cookie per line and each becomes its own run; your connected runners pull them as they free up, so a batch of 50 runs spreads across 5 runners automatically. Each row is type-checked before it is queued, and the batch summary counts the detected frameworks. The backlog lists every run with its live state, detected type, and result (the recovered key), and you can open a run to stream its output or cancel it. You can also fetch a URL instead of pasting cookies: the runner grabs the Set-Cookie headers from that URL and cracks them. A wordlist is uploaded once to object storage and shared by the whole batch. Submitting and cancelling require a token with the Tool Runs write scope; reading requires the read scope. The runner decodes and unsigns cookies natively — no toolchain download and no network access beyond the cookie or URL you provide.

Notifications for finished runs are not wired up yet.

#Reliability

Queued runs are persisted in the platform database, not a transient cache, so they survive hub and runner restarts. A run claimed by a runner carries a lease that the runner renews on its heartbeat; if the runner dies mid-run the lease expires and the run is automatically re-queued for another runner. Redis only carries wake-up notifications — a Redis restart can delay a pickup by a few seconds but never loses a run.

#Limits

Tool runs are limited per plan, per account (across all your runners):

PlanConcurrentQueuedStarts / minRetention
Free5100157 days
Pro155004530 days
Elite40200012090 days

Extra runs wait in the queue until a slot frees. Submitting past the queue cap is rejected. Finished runs are deleted after the retention window.

#Automating it

For scheduled or dataset-driven use, the same tool is available as the platform module bountyhub/cookielab and the cookie-session-audit workflow template. The module accepts decoder (a comma-separated format list, or auto) and wordlist_format (base64 or plain) alongside cookie, url, and wordlist. See Modules.

#Authorization

Only test sessions you are permitted to assess. This tool exists to validate your own deployments or authorized engagement targets.