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.comcsrf 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@gmail.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:petercarlos: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.
Lab 5: CSRF where token is tied to non-session cookie
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:petercarlos: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
Lab 6: CSRF where token is duplicated in cookie
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
Secureattribute 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
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
Laxrestriction level.This means session cookie will b send in cross-site
GETrequests.
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 ❌❌❌❌❌❌❌❌❌❌❌❌❌❌❌❌❌❌
Lab 10: SameSite Lax bypass via cookie refresh
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-loginendpoint 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