Skip to content

Instantly share code, notes, and snippets.

@chriselgee
Last active October 14, 2023 01:23
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save chriselgee/b9f1861dd9b99a8c1ed30066b25ff80b to your computer and use it in GitHub Desktop.
Save chriselgee/b9f1861dd9b99a8c1ed30066b25ff80b to your computer and use it in GitHub Desktop.
Decoding Flask Cookies with Python and Cyber Chef

Flask cookies, when stored client-side, are .-delimited, often zlib-deflated, and Base64-encoded with _ subbed in for / and - subbed in for + (URL-safe encoding).

Let's take an example cookie from https://snowball2.kringlecastle.com/:

.eJy1kT8PgjAQxb9L5w7UIv9mNJoYB3UjDI1WJQE0IENj_O6WZxFQYhw0l7z23l1yvV-vJEz2-2RbpRdFAouSSS4ztRDqVF1IEEUWfYuYapf90WXdgDv8BqvX23WHe_tubHZdH5NzWa8aPaaNoBxqQ8da9aFPH5kHdaGOqXBkNnQMz0WHqztqbTyOzI7r8dMikfku_YJ2E_1Nf0v71W1ndml_dj_SbtZtgQ-jppFjgHsGF4f3QMxRYYDLAJcZuC3-9mNcfJajtX7BpipyEpBzKpQsCDWXeai9WXU4rkRenrKwUOVOpPJZX4pM6g7f9rjv-CNObncEAMTx.YaTaAA.SGRJEzFnk9BCtFwX-SmuSHrKofM

We can take the first piece (ignoring the signature) and store it as a variable in python3:

>>> cookie = "eJy1kT8PgjAQxb9L5w7UIv9mNJoYB3UjDI1WJQE0IENj_O6WZxFQYhw0l7z23l1yvV-vJEz2-2RbpRdFAouSSS4ztRDqVF1IEEUWfYuYapf90WXdgDv8BqvX23WHe_tubHZdH5NzWa8aPaaNoBxqQ8da9aFPH5kHdaGOqXBkNnQMz0WHqztqbTyOzI7r8dMikfku_YJ2E_1Nf0v71W1ndml_dj_SbtZtgQ-jppFjgHsGF4f3QMxRYYDLAJcZuC3-9mNcfJajtX7BpipyEpBzKpQsCDWXeai9WXU4rkRenrKwUOVOpPJZX4pM6g7f9rjv-CNObncEAMTx"

Then we import the libraries we need:

>>> import zlib; import itsdangerous

Then decode and decompress:

>>> zlib.decompress(itsdangerous.base64_decode(cookie))

And we get the resulting bytes:

b'{"Difficulty":0,"EnemyLayout":[[0,0,0,0,0,0,0,0,0,0],[0,1,0,0,0,0,0,0,0,0],[0,1,0,0,0,0,0,0,0,0],[0,1,0,0,0,0,0,0,0,0],[0,1,0,0,0,0,0,0,0,0],[0,1,0,1,1,1,1,1,1,1],[0,0,0,0,0,0,0,0,0,0],[0,0,0,1,1,1,1,1,0,0],[0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0]],"EnemyShips":[[[1,1],[2,1],[3,1],[4,1],[5,1]],[[5,9],[5,8],[5,7],[5,6]],[[5,3],[5,4],[5,5]],[[7,7],[7,6],[7,5]],[[7,3],[7,4]]],"FriendlyLayout":[[0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,1,1,1,0,0],[0,1,0,0,0,0,0,0,0,0],[0,1,0,0,0,0,0,0,0,0],[0,1,0,0,0,0,0,0,0,0],[0,1,0,1,1,1,1,0,0,0],[0,1,0,1,0,0,0,0,1,0],[0,0,0,1,0,0,0,0,1,0],[0,0,0,1,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0]],"FriendlyShips":[[[2,1],[3,1],[4,1],[5,1],[6,1]],[[8,3],[7,3],[6,3],[5,3]],[[1,7],[1,6],[1,5]],[[5,4],[5,5],[5,6]],[[7,8],[6,8]]],"Turn":"player","playerID":"HughRansomDrysdale","playerName":"948396923"}'

Yay!

The same can be done with Cyber Chef:

  • Put the cookie in the Input field
  • Drag From Base64 and Zlib Inflate into the Recipe
  • Set the Base64 alphabet to URL safe
  • Bake and poof! You get Output like:
{"Difficulty":0,"EnemyLayout":[[0,0,0,0,0,0,0,0,0,0],[0,1,0,0,0,0,0,0,0,0],[0,1,0,0,0,0,0,0,0,0],[0,1,0,0,0,0,0,0,0,0],[0,1,0,0,0,0,0,0,0,0],[0,1,0,1,1,1,1,1,1,1],[0,0,0,0,0,0,0,0,0,0],[0,0,0,1,1,1,1,1,0,0],[0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0]],"EnemyShips":[[[1,1],[2,1],[3,1],[4,1],[5,1]],[[5,9],[5,8],[5,7],[5,6]],[[5,3],[5,4],[5,5]],[[7,7],[7,6],[7,5]],[[7,3],[7,4]]],"FriendlyLayout":[[0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,1,1,1,0,0],[0,1,0,0,0,0,0,0,0,0],[0,1,0,0,0,0,0,0,0,0],[0,1,0,0,0,0,0,0,0,0],[0,1,0,1,1,1,1,0,0,0],[0,1,0,1,0,0,0,0,1,0],[0,0,0,1,0,0,0,0,1,0],[0,0,0,1,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0]],"FriendlyShips":[[[2,1],[3,1],[4,1],[5,1],[6,1]],[[8,3],[7,3],[6,3],[5,3]],[[1,7],[1,6],[1,5]],[[5,4],[5,5],[5,6]],[[7,8],[6,8]]],"Turn":"player","playerID":"HughRansomDrysdale","playerName":"948396923"}

Cyber Chef example here.

@detinsley1s
Copy link

I found two typos. In line 1, "zlip-deflated" should be "zlib-deflated". Also, in the first line under the top scrolling box, "variable" is misspelled.

@PhroggDev
Copy link

PhroggDev commented Dec 10, 2021

I was wondering how to zlip-deflate something. But I figured it out when I got to Python "varialbe" and importing zlib.
Howdy from KringleCon 4
Nice to see two easy ways of doing this.

@chriselgee
Copy link
Author

Aha - thank you both! I've also added the caveat that they are "often" zlib deflated. Developers who are more sparing with session in Flask may find theirs don't need compression. (-:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment