> 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-1.md).

# Lab 1

### What is CSRF?

Cross-site request forgery (also known as CSRF) is a web security vulnerability that allows an attacker to induce users to perform actions that they do not intend to perform. It allows an attacker to partly circumvent the same origin policy, which is designed to prevent different websites from interfering with each other. For example, this might be to change the email address on their account, to change their password, or to make a funds transfer.

#### The 3 conditions simply

**1. A relevant action** There has to be something worth doing — changing password, transferring money, changing email, promoting a user to admin. No point attacking if the action has no value.

**2. Cookie-based session handling** The app identifies you **only** by your cookie. No extra verification like "re-enter your password" or a token. Just the cookie.

This matters because your browser **automatically sends cookies** to any site that matches the domain — you don't control that, the browser does it for you.

**3. No unpredictable parameters** The attacker needs to be able to construct the full request in advance. If changing your password requires knowing your **current** password — the attacker can't forge it because they don't know it.

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

1. User logs into bank.com normally → browser stores bank.com session cookie
2. Separately, user visits evil.com (hacker's site) → maybe from a phishing email, random link, etc.
3. evil.com's page silently fires a request to bank.com → browser sees "this request is going to bank.com" → browser auto-attaches the bank.com cookie it already has
4. bank.com receives request + valid cookie → thinks it's the user → executes the action

### Isn't it just Phishing?&#x20;

The hacker's job is to **construct a valid request** that the real server will accept. That's the technical work. A properly built server should reject that forged request because it came from `evil.com` not `bank.com`. The fix is a **CSRF token** — a secret random value embedded in every form that the server checks. The hacker can't forge it because they can't read it from `bank.com` (cross-origin restrictions).

If the server has no CSRF token → any forged request from anywhere gets accepted → vulnerable.<br>

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

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

Doing this exploit let's us change the email, but it doesn't solve the lab. We need to put a little more:

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

### Why it works?&#x20;

#### Full methodology breakdown

***

#### The attacker server

PortSwigger gives you a **free exploit hosting server** for the lab. In real life this would be:

* A VPS the hacker rents
* A fake website they built
* Any page they can get the victim to visit

It's just a place to host the malicious HTML page.

***

#### What the victim needs to do

Just **visit the URL** of your exploit page. That's it. Nothing else.

In real life the hacker would send:

* A phishing email with the link
* A fake ad
* A message on social media

In the lab — "Deliver to victim" simulates the victim clicking the link.

***

#### Why the `<script>` tag matters

Without it:

html

```html
<form method="POST" action="https://bank.com/change-email">
  <input type="hidden" name="email" value="hacker@evil.com">
</form>
```

The form exists on the page but **nothing submits it**. The victim would have to click a submit button themselves.

With it:

```html
<script>document.forms[0].submit()</script>
```

The moment the page loads → JavaScript instantly submits the form → victim sees nothing → request fires automatically.

That's why the lab didn't solve until you added it — without it you submitted the form **as yourself** manually. The victim auto-submission never happened.
