SameSite Strict bypass via client side redirect

Description

This lab's change email function is vulnerable to CSRF. To solve the lab, perform a CSRF attackarrow-up-right 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

Approach

Upon logging in, I noticed the following response header indicating that SameSite protection is enabled and set to Strict:

Set-Cookie: session=ZiIDBue8O418Mu3AzTlA27Uckxe0oTRF; Secure; HttpOnly; SameSite=Strict

This means that cross-site requests won't include the necessary cookies. To bypass this restriction, I needed to find a way to perform a CSRF attack that would still include the required cookies. A client-side redirect can achieve this, as it is treated as an ordinary, standalone request that includes all relevant cookies.

I began searching for a way to achieve an open redirect on the client side. While navigating the website, I couldn't find anything immediately useful, so I reviewed my Burp Suite HTTP history to check for any interesting background requests. I found the following request:

GET /resources/js/commentConfirmationRedirect.js HTTP/2
Host: 0a5e00fa038310658033217e002700ce.web-security-academy.net
Cookie: session=ZiIDBue8O418Mu3AzTlA27Uckxe0oTRF
...

The response was:

HTTP/2 200 OK
Content-Type: application/javascript; charset=utf-8
Cache-Control: public, max-age=3600
X-Frame-Options: SAMEORIGIN
Content-Length: 231

redirectOnConfirmation = (blogPath) => {
    setTimeout(() => {
        const url = new URL(window.location);
        const postId = url.searchParams.get("postId");
        window.location = blogPath + '/' + postId;
    }, 3000);
}

This JavaScript file handles the redirection process after submitting a comment. When I submit a comment, the following requests are sent:

  1. POST /post/comment

  2. GET /post/comment/confirmation?postId=9

  3. GET /resources/js/commentConfirmationRedirect.js

  4. GET /post/9

After posting a comment, the page redirects to the comment confirmation page with the postId parameter. The script then appends the postId value to the blog path to construct the redirect URL.

I had an idea to use path traversal to navigate from /post/9 to /my-account. I tried navigating to GET /post/comment/confirmation?postId=../my-account, and after a few seconds, I was redirected to the /my-account page. This confirmed that the idea worked.

Next, I needed to verify if changing the email via a GET request was possible. I sent the POST /my-account/change-email request to repeater, right-clicked on the request, and selected "Change request method" to GET. The request worked, confirming that changing the email through a GET request is possible.

I constructed the full URL for the attack:

I included the submit parameter because it is present in the form:

After waiting a few seconds, I was redirected to the my-account page with the new email, confirming the attack worked.

Next, I built the exploit payload:

When I clicked Store and Deliver exploit to victim, the victim was taken to the comment confirmation page. The redirection in the postId parameter enabled the email change. Since this is a client-side redirection, it included all cookies, including session cookies. As a result, the lab was solved, and the victim's email was successfully changed.