--- title: XSS Through the Referer Header tags: - Security description: In this blog post, I document how I achieved reflected XSS though a malicious http header. date: 2021-10-14 --- XSS is a vulnerability in which a malicious actor is able to run JavaScript in an unsuspecting clients browser session. Normally, this is done via input fields whose values are reflected back to the user without proper sanitisation. In this blog, I demonstrate a method I recently used that injected the payload via the Referer [sip] header. Only do this on websites you own or have permission to do so no. It is illegal in most places to do this without permission. ## Initial foothold I found myself looking at a website whose input fields were all well sanitised, getting ready to write a pretty boring report. However, I spotted a snippet of JavaScript in an analytics script that looked something like this: ```js ``` That sparked my interest so I opened pappy and changed the referer header to `" + alert(1),"":"`. BRILLIANT! That worked. The referer header was not being sanitised. ## Crafting the referer header So, that is nice, but it would take some serious social engineering to convince someone to intercept a request in burp / pappy / some other proxy tool, change their referer header to our payload and then submit the request. Really we needed a way to control that header ourselves. For anyone that doesn't know, the [referer header](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referer) holds the address of the page that makes the request. This basically means the previous page if a link was clicked. There is also a related header called [referrer-policy](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referrer-Policy) that controls how much information is sent. I want to send as much as possible so I manually set this to `unsafe-url` for my proof of concept. ```php ``` I am using php here because I know it. I'm not saying php is the best choice. Use what you know and can use quickly for proof of concepts. My initial thought was to simply use HTTP redirects to first redirect the user to a page whose url contained my payload, and then from there to the vulnerable page. The code for that was: ```php ``` That didn't work. After some searching I realised that the referer header is not changed when an http redirect is followed. It does however if the url is changed with JS. ```php $payload='"+alert(1),"":"'; header('Referrer-Policy: unsafe-url'); if ( $_SERVER['REQUEST_URI'] == "/index.php" ) { $location='//localhost:8081/index.php/' . urlencode($payload); }else{ $location='https://vulnerable-site.com/page'; }