Stealing OAuth tokens from the LinkedIn API using meta referrer

Meta referrer is a proposal from WhatWG which is implemented in WebKit and allows us to control the circumstances under which the Referer (sic) header is sent when fetching page resources.

Let it first be said that in my opinion if you’re enforcing any kind of security based on the Referer header, this should be a sanity check at best.

I noticed recently when accessing LinkedIn‘s online help system that an authentication interstitial was shown when first loading the page. I’ve never used the LinkedIn API before so I was curious as to how this was handled over plain HTTP, so cracked open the Chrome developer tools and got to work examining what was happening during this interstitial.

I quickly found a request to a JavaScript file including the API key for the help system which immediately returned an OAuth token for the user. (File as it was)

I tried just including this file in a local HTML page.

Screen Shot 2013-07-04 at 09.56.20

A part of the JavaScript was checking matched one of a number of predefined hostname masks.

No problem. Remember we can override primitives & their prototypes in JavaScript. Just include this above it.

window.String.prototype._match = window.String.prototype.match; window.String.prototype.match = function (pattern) { return true; };

With this in place, I could now add an extra piece to give me the OAuth token once it had been loaded:

Job done, this now worked on my local machine. Let’s try it on the open web…

Screen Shot 2013-07-04 at 09.56.20

This again? Now it seems that userspace.js is serving up different content.

After some thought, it occurred to me that the only thing different between this request and the load request was the Referer header. The back-end must be doing something “clever” and restricted access by this header. Sure enough, opening the file on its own in a new tab works. Thanks to support for Meta referrer in WebKit, we can get rid of this annoyance just by adding

<meta name="referrer" content="never">

to our HTML file. And it works!

Successful token stealing

So, what did we learn? You shouldn’t trust JavaScript or the Referer header exclusively for any kind of authorization policy.

I reported this to LinkedIn on 3rd July 2013 and they reported it as fixed (by disabling requests without referrers) on 5th July 2013. I received a LinkedIn T-shirt all the way from California for my troubles.