The lab
here is how portswigger describes it
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
Note
The default SameSite restrictions differ between browsers. As the victim uses Chrome, we recommend also using Chrome (or Burp's built-in Chromium browser) to test your exploit.
the earlier csrf labs all gave us a token to defeat but this one has no token at all its only defence is the browser's own SameSite cookie behaviour
first, why the browser matters. SameSite defaults are not the same across browsers, and the simulated victim is on chrome, which treats a cookie with no explicit SameSite attribute as Lax by default and that default is exactly what we are bypassing. so we test in the same engine the victim uses burp's built in chromium browser, otherwise firefox's different handling could make our exploit behave differently and send us chasing the wrong thing.
The idea#
SameSite is a cookie attribute that decides when the browser will attach a cookie to a request coming from a different site. Lax which chrome applies on its own when the site does not set SameSite itself, is a middle setting. it holds the cookie back on most cross site requests, background fetches, images, cross site form posts but it makes one exception it will still send the cookie on a top level navigation that uses a safe method meaning the whole browser window is navigating to the target through a get the way following a link does.
that one exception is the entire attack. if we can get the victim's browser to do a top level get navigation to the change email endpoint, Lax will let the session cookie ride along and since there is no csrf token to supply that request is authenticated and complete. the only problem will be that the endpoint wants a post and we will deal with that with a small trick
Step 1 - Log in and check for a Token#
logging in and intercepting an email change request i sent it to repeater and looked it over

there is no csrf token anywhere in the request so if we can get past the cookie rules this could be a plain unprotected action

checking the response, the server never sets an explicit SameSite attribute on the session cookie either, which means chrome falls back to its Lax default and that is the behaviour we just described. so the plan is set, force a top level get navigation and let Lax do the rest
Step 2 - the Endpoint wants post so override the method#
the catch is that Lax only sends the cookie on a get but the change email endpoint only accepts a post. sending a plain get proves it
GET /my-account/change-email?email=foo%40web-security-academy.net

it comes back method not allowed. we need a request that leaves the browser as a get, so the cookie is attached, but that the server ends up treating as a post. that is what a method override is for. lot of web frameworks let you add a _method parameter to say which http method the request should really be handled as whatever it actually arrived as so we send a get with _method=POST on the query string
GET /my-account/change-email?email=foo%40web-security-academy.net&_method=POST

the server accepts it so a get carries the cookie under Lax, the _method=POST makes the server run it as the email change and we have both at once
Step 3 - Build the POC and deliver it#
so the payload just has to send the victim's whole browser window to that url, because only a top level get navigation gets the cookie attached, a background request or an image would not count the simplest way to do that is to set document.location and let the browser navigate there itself. here is the page for the exploit server.
<script>
document.location = "https://your-lab-id.web-security-academy.net/my-account/[email protected]&_method=POST"
</script>
when the victim opens this the script navigates their top level window to our crafted url. because that is a top level get navigation, chrome attaches the session cookie under Lax, the _method=POST tells the server to process it as the change email post and with no token needed the email is changed.

with this, the lab is solved!
