Last year we’ve been playing with a very simple method to spoof the referrer on Edge, which allowed us of course to spoof the referrer and -as a bonus- other neat things like bypass the XSS filter.
Today I found out that it was patched, so I decided to give it a try and find a way around the patch. Honestly I don’t feel it’s a bypass but clearly a variation. From a practical point of view, it works again and bypasses the patch, but from a technical point of view, the method is somewhat different. Either way, let’s go for it!
In a hurry? Watch the 12 sec video where we quickly show what can be done with this vulnerability.
Original PoC before the patch
In the original post we’ve seen that we could spoof the referrer by simply opening a new window with the desired referrer and then, moving to the target location. Two lines of code are worth a thousand words. 🙂 Check out the PoC below, where whatismyreferrer.com thinks (not anymore, it’s patched!) that the referrer is paypal.com when in reality, it should be the URL of the page that executes the location.href.
win = window.open("https://www.paypal.com"); win.location.href = "https://www.whatismyreferer.com";
That was enough to spoof the referrer on Edge but it’s patched now, however, an easy variation stumbled upon me. No debugger or analysis here, just a plain bold test which quickly worked.
I tried a couple of methods to change the final URL (instead of location.href, using location.replace, meta refresh, window.open, etc) to see if Edge could be fooled again, but all of them failed. But, what would happen if the URL is changed from inside an iframe? Will the referrer be the top or iframe URL?
Playing with the referrer
Before answering that question keep in mind that normally, the referrer should be the URL that initiated the request. Let’s say we have facebook.com with an iframe pointing evil.com, if the iframe changes the top URL to paypal.com, the referrer received by paypal should be evil and not facebook.
The image above shows the expected (and correct) behavior even on Edge. However, if instead of using a regular link, we set the location of the top via location.href, then, Edge gets confused and uses the top as the referrer.
Below is simple test page which shows the difference between a regular link and location.href to change the top URL. Both take you to whatismyreferer.com but as you will see, the regular link behaves properly while the top.location.href does not.
[ Test page showing the vulnerability ]
But how can we use this vulnerability? It’s obvious that facebook will never host evil, right? Well, facebook like yahoo and almost every big one hosts iframes with ads. Those ads are capable of loading any page on behalf of those big web-sites. Also, using top.location.href those ads can bypass the XSS filter without problems.
Personally, I hate theoretical vulnerabilities because they give me no satisfaction at all. You know, the kind of “if the user clicks here, accepts the warning, decompresses the zip and double clicks on the exe, he gets infected“. Don’t like.
Our goal to create a working exploit is by injecting an iframe into the spoofed-referrer site and then, execute a top.location from it. This will we the same as being framed in any site, but, we won’t need its cooperation! Makes sense? Let’s say we want whatismyreferer.com (victim) to believe the user is coming from paypal.com (spoofed referrer). How can we do that?
Injecting an iframe
- Open a new window with a server redirect to Paypal.
- Before the redirect happens, inject an iframe.
- Once redirected, from within the iframe do a top.location to whatismyreferer.com
This iframe injection has been previously described at the bottom of the htmlFile/UXSS on IE post, but let’s do a quick recap here.
When we open the new window with the server redirect (1), we have a bit of time (before the redirect happens) to access its DOM, and that’s when we inject the iframe (2). Once the redirection happens, Edge will do its best to remove everything from the page (including our iframe) and render paypal, however, we will prevent that by blocking the thread. Then, once the redirection happens we will unblock the thread and execute a top.location.href (3) from inside the iframe.
In this particular case we will block the thread using the same technique as here or here, just an ugly-visible-bold alert. Of course there are ways to block it without the alert and no user interaction, but we don’t want to make attacker’s lives easy: if the PoC needs an alert and the user must interact, it becomes less useful. Here’s the full PoC.
// Open a new window with a server redirect to paypal var win = window.open("redir.php?URL=https://www.paypal.com"); // Create an iframe immediately, before it redirects var ifr = win.document.createElement("iframe"); win.document.appendChild(ifr); // Make sure the iframe has access to its top (otherwise it will lose it) win.opener = win; // Block the iframe and once the redirect happens, move to the victim website. win.setTimeout("alert('Close me once the site starts loading behind');" + "opener.location='https://www.whatismyreferer.com'");
[ Test the PoC Live on Edge ]
Bug hunter, never stop learning! Close that facebook tab and keep reading interesting things. Life is beautiful and short, don’t waste your potential spending minutes on things (or sites) that don’t give you anything back. Learn learn and learn. Find things, alternatives, and enjoy your findings!
Have a nice day! 🙂