For the complete documentation index, see llms.txt. This page is also available as Markdown.

CSRF Attacks (Labs: PortSwigger Academy)

Labs from PortSwigger Academy

🟩🟩APPRENTICE LAB🟩🟩

Lab 1: CSRF vulnerability with no defenses

This lab's email change functionality is vulnerable to CSRF. To solve the lab, craft some HTML that uses a CSRF attack to change the viewer's email address and upload it to your exploit server. You can log in to your own account using the following credentials: wiener:peter

request to change-email

POST /my-account/change-email HTTP/2
Host: 0a15007803dd362b80f526d800280014.web-security-academy.net
Cookie: session=JInuAPKthk1MKjumyhIusKUJw2pkdLTD
Content-Type: application/x-www-form-urlencoded
Content-Length: 22

email=test%40gmail.com

csrf poc

<html>
  <!-- CSRF PoC - generated by Burp Suite Professional -->
  <body>
    <form action="https://0a15007803dd362b80f526d800280014.web-security-academy.net/my-account/change-email" method="POST">
      <input type="hidden" name="email" value="dollarboysushil&#64;gmail&#46;com" />
      <input type="submit" value="Submit request" />
    </form>
    <script>
      history.pushState('', '', '/');
      document.forms[0].submit();
    </script>
  </body>
</html>

🟦🟦PRACTITIONER LABS🟦🟦

Lab 2: CSRF where token validation depends on request method

This lab's email change functionality is vulnerable to CSRF. It attempts to block CSRF attacks, but only applies defenses to certain types of requests. To solve the lab, use your exploit server to host an HTML page that uses a CSRF attack to change the viewer's email address. You can log in to your own account using the following credentials: wiener:peter

request to change email

there exist csrf protection mechanism with the use of csrf token

but this protection mechanism doesnot exist in GET request. so, remove csrf token and change request to GET

final request without csrf protection

POC

Lab 3: CSRF where token validation depends on token being present

This lab's email change functionality is vulnerable to CSRF. To solve the lab, use your exploit server to host an HTML page that uses a CSRF attack to change the viewer's email address. You can log in to your own account using the following credentials: wiener:peter

email change request

we can simply remove the csrf parameter and token.

final email change request

POC

Lab 4: CSRF where token is not tied to user session

This lab's email change functionality is vulnerable to CSRF. It uses tokens to try to prevent CSRF attacks, but they aren't integrated into the site's session handling system. To solve the lab, use your exploit server to host an HTML page that uses a CSRF attack to change the viewer's email address. You have two accounts on the application that you can use to help design your attack. The credentials are as follows:

  • wiener:peter

  • carlos:montoya

email change request

CSRF token is valid for one request and is not tied to sessions. Which means we can intercept any email change request and get the csrf token and use it for other account.

POC

In this situation, the attacker can log in to the application using their own account, obtain a valid token, and then feed that token to the victim user in their CSRF attack.

This lab's email change functionality is vulnerable to CSRF. It uses tokens to try to prevent CSRF attacks, but they aren't fully integrated into the site's session handling system. To solve the lab, use your exploit server to host an HTML page that uses a CSRF attack to change the viewer's email address. You have two accounts on the application that you can use to help design your attack. The credentials are as follows:

  • wiener:peter

  • carlos:montoya

Change email request

Findings

  • csrfKey and csrf token are tied to each other

  • csrfKey and csrf token are not tied to session cookie, which means we can use these token of other user.

To exploit the CSRF we need to make sure victim's csrfKey is what we desire.

Search feature looks interesting. request:

response:

This means search term gets reflected in the Set-Cookie header. using the search request we can set cookie. Lets set csrfKey

request:

%0d%0a --> carriage return or new line response:

POC to set csrfKey

POC to change email

This lab's email change functionality is vulnerable to CSRF. It attempts to use the insecure "double submit" CSRF prevention technique. To solve the lab, use your exploit server to host an HTML page that uses a CSRF attack to change the viewer's email address. You can log in to your own account using the following credentials: wiener:peter

email change request

there exist csrf token in body of the request and in the header.

The checking mechanism of csrf token in based on client side. It just checks if the both the csrf token is same. So, we need to find a way to set csrf cookie.

This lab is similar to previous one, we can use the search feature to set up cookie.

request to set cookie using search feature:

POC to set csrf cookie

POC to change email

Same Site vs Same Origin

Request from

Request to

Same-site?

Same-origin?

https://example.com

https://example.com

Yes

Yes

https://app.example.com

https://intranet.example.com

Yes

No: mismatched domain name

https://example.com

https://example.com:8080

Yes

No: mismatched port

https://example.com

https://example.co.uk

No: mismatched eTLD

No: mismatched domain name

https://example.com

http://example.com

No: mismatched scheme

No: mismatched scheme

All major browsers currently support the following SameSite restriction levels:

SameSite = Strict (most secure)

  • The cookie is only sent if the request comes from the same site currently open in the address bar.

  • If you click a link or submit a form from another domain — even if it navigates to the target site — the cookie will not be sent.

✅ Great for: Sensitive cookies (authentication sessions, admin dashboards, etc.)

❌ Bad for: Cross-site workflows — like logging in through a redirect, sharing links, or “Continue with...” buttons that rely on third-party redirects.

Example Set-Cookie: session=abc; SameSite=Strict → Only sent when the user is already on the same site.

SameSite = Lax (default for most browsers)

  • The cookie is sent for top-level GET navigations (when you click a normal link).

  • But not sent for cross-site POSTs, iframes, or background requests triggered by JavaScript.

✅ Helps block most CSRF attacks (which usually use POST). ✅ Still allows navigation links to work normally.

Example

Set-Cookie: session=abc; SameSite=Lax → Sent when clicking a normal link to the site, but not when submitting a hidden POST form from another domain.

SameSite = None (least secure)

  • The cookie is sent with all requests, even from third-party contexts.

  • But you must also add Secure attribute to ensure cookie is only sent in encrypted messages over HTTPS (otherwise browsers will reject it).

✅ Needed for: Third-party integrations, tracking cookies, embedded widgets, or cross-domain apps that rely on shared cookies.

❌ Dangerous for: Session cookies — since it allows full cross-site cookie sending (and therefore CSRF).

Example Set-Cookie: trackingId=abc; SameSite=None; Secure

🧩 Summary Table

SameSite Value
Sent in Cross-Site GET
Sent in Cross-Site POST
Use Case
CSRF Risk

Strict

❌ No

❌ No

Highly sensitive sessions

🚫 None

Lax

✅ Only top-level GETs

❌ No

Typical logins / user sessions

⚠️ Low

None

✅ Yes

✅ Yes

Third-party/tracking cookies

🔥 High

Lab 7: SameSite Lax bypass via method override

This lab's change email function is vulnerable to CSRF. To solve the lab, perform a CSRF attack that changes the victim's email address. You should use the provided exploit server to host your attack.

You can log in to your own account using the following credentials: wiener:peter

email change request:

  • No unpredictable tokens, so may be vulnerable to CSRF

  • website doesn't explicitly specify any SameSite restrictions when setting session cookies. As a result, the browser will use the default Lax restriction level.

  • This means session cookie will b send in cross-site GET requests.

Changing the request to GET doesnot work. "Method Not Allowed" This can be bypassed by using _method Method spoofing

response: 200 OK Explaination: many web apps include a method-override step that looks for a special marker (commonly _method in the query string or form body, or the X-HTTP-Method-Override header) and then rewrites the request’s effective method before the app routes/handles it. If the server accepts _method from the query string, a cross-site GET like GET /change-email?email=...&_method=POST can be rewritten server-side to behave like a POST, so state-changing code runs.

CSRF Poc

Lab 8: SameSite Strict bypass via client-side redirect

This lab's change email function is vulnerable to CSRF. To solve the lab, perform a CSRF attack that changes the victim's email address. You should use the provided exploit server to host your attack.

You can log in to your own account using the following credentials: wiener:peter

login request and response:

SameSite=Strict --> victim's browser wont include session cookie in any cross site request.

There exist redirection after posting comment

redirection request:

value of postId is passed for redirection.

actual redirection code (commentConfirmationRedirect.js)

value of postId is appended to /post.

checking our custom redirection. request

this is redirected to

/post can be removed by path traversal

this redirects to

Phase 2: email change request

method spoofing

combining them. Using this change-email GET request in redirection url.

final csrf request is:

POC

Lab 9: SameSite Strict bypass via sibling domain

This lab's live chat feature is vulnerable to cross-site WebSocket hijacking (CSWSH). To solve the lab, log in to the victim's account.

To do this, use the provided exploit server to perform a CSWSH attack that exfiltrates the victim's chat history to the default Burp Collaborator server. The chat history contains the login credentials in plain text.

If you haven't done so already, we recommend completing our topic on WebSocket vulnerabilities before attempting this lab.

❌❌❌❌❌❌❌❌❌❌❌❌❌❌❌❌❌❌ will be completed later ❌❌❌❌❌❌❌❌❌❌❌❌❌❌❌❌❌❌

This lab's change email function is vulnerable to CSRF. To solve the lab, perform a CSRF attack that changes the victim's email address. You should use the provided exploit server to host your attack.

The lab supports OAuth-based login. You can log in via your social media account with the following credentials: wiener:peter

If a website doesn't include a SameSite attribute when setting a cookie, Chrome automatically applies Lax restrictions by default. However, to avoid breaking single sign-on (SSO) mechanisms, it doesn't actually enforce these restrictions for the first 120 seconds on top-level POST requests.

Finding 1:

This request is responsible for automatically initiating the full OAuth flow. If we are still logged-in with the OAuth server, this all happens without any interaction. And every time the OAuth flow is completed, webapp sets a new session cookie.

Our main idea next is to, make the webapp use this request to regenerate the session cookie and within 120 sec of new cookie generation, we use CSRF attack. This way SameSite Lax restriction will not be enforced for first 120 seconds on top-level POST request.

CSRF POC

POC explaination

STEP 1:

  • When victim clicks anywhere on the page, this code runs.

  • It opens a newtab to site /social-login.

  • This is a top-level GET request, so because SameSite=Lax allows cookies on top-level GET navigations, the browser sends the session cookie for the request.

  • The /social-login endpoint reset the session cookie.

STEP 2:

This sends a POST request to /my-account/change-email with the hidden email parameter.

Why it works Under normal SameSite=Lax rules:

  • A cross-site POST request (like this CSRF form) would not include cookies.

  • But because the cookie was just refreshed via a top-level GET navigation to the target domain, the browser treats the cookie as “recently used” — so it temporarily bypasses the Lax restriction for a very short window (a few seconds). This is the “SameSite=Lax cookie refresh” bypass. It exploits the browser’s grace period for freshly set cookies — allowing the POST request to include the session cookie even though it’s cross-site.

Lab 11: CSRF where Referer validation depends on header being present

This lab's email change functionality is vulnerable to CSRF. It attempts to block cross domain requests but has an insecure fallback.

To solve the lab, use your exploit server to host an HTML page that uses a CSRF attack to change the viewer's email address.

You can log in to your own account using the following credentials: wiener:peter

The csrf protection depends on the referrer header. Webapp rejects all the request which contains referer header outside its domain. This can be bypassed by simply removing the Referer header from the request

POC

<meta name="referrer" content="no-referrer"> --> this html suppress the Referer header.

Lab 12: CSRF with broken Referer validation

This lab's email change functionality is vulnerable to CSRF. It attempts to detect and block cross domain requests, but the detection mechanism can be bypassed.

To solve the lab, use your exploit server to host an HTML page that uses a CSRF attack to change the viewer's email address.

You can log in to your own account using the following credentials: wiener:peter

This time also CSRF protection depends on the Referer header. Unlike previous lab, CSRF header cannot be removed.

request to update email:

we can bypass the Referer header by making the original url as query string:

Barebone POC:

In this poc, we need to implement the change of Referer header and this can be achieved by using following javascript. history.pushState("", "", "")

There are 3 parameters in above javascript

  • 1st "" --> State object

  • 2nd "" --> title

  • 3rd "" --> URL

FINAL POC

The final request on behalf of victim is:

/?0ab9008803f0c01285a167ff00da0036.web-security-academy.net is appended to the end of the actual Referer header

Last updated