zemnmez
Thomas Shadwell LogoA 2D pyramidal frustum (triangle with the top missing). In the center is an open eye, below the eye, a single tear.
Thomas NJ Shadwell

This page is a rendering of the text in the original document, which was made with hand-written HTML. It can be seen in its original formatting in the archived version of this article.

WHEN SECURITY GENERATES INSECURITY

Detecting login state for almost any website on the internet

For those who don’t know, Content-Security-Policy or CSP is an attempt at mitigating Cross Site Scripting (XSS) attacks which are generally what you aim for when you manipulate a web endpoint – a web page – such that you can inject your own client-side code.

It’s problematic because an unrestricted XSS attacker operates from the trust level of the website the injection was made in, allowing access to user sessions and details; anything the user can access or manipulate the attacker can.

With the popularity of content-unaware templating systems such as PHP's built in system, security often becomes clumsy to implement, where a programmer would like to write (though EOD is more often used over single quotes in this case) <?php echo "<a href=\"$link\">$name</a>"; ?> for a menu of theirs they immediately introduce such exploits if the content of the used variables is not already sanitised.

Who is the browser working for?

Content-Security-Policy headers take the form of a semicolon separated list of statements each describing one aspect of the policy. Each of these statements may have several comma separated statements that describe what resources to allow. For example, the CSP Content-Security-Policy: default-src 'self' *.google.com; image-src *.akamaihd.net only allows resources from this origin, and images only from some sub-domain of ‘akamaihd.net’.

There are additional directives for some other useful features such as sandboxing certain features of the web page, but most interestingly a report-uri directive for specifying a place to send breaches of the policy to.

The report-uri feature intrigued me, it’s uncharacteristic of such technologies to report back information on what the user navigated to because it leaks information about the user's browsing habits.

Detecting a login

Interest piqued by the report-uri feature, I looked into abusing it to glean information about user state, my idea was this: when a user is not logged into Google Calendar, accessing calendar.google.com redirects them to accounts.google.com via a Location header. If I whitelisted ‘calendar.google.com’ but not ‘accounts.google.com’, accessing that resource within my web page would break CSP, subsequently sending me a message telling me whether they were logged into Google.

The implementation was like this: I had a single image on the page <img src="http://calendar.google.com"/>, and I sent the Content-Security-Policy header Content-Security-Policy: image-src calendar.google.com. The test was a success, I was able to detect login on Google. The same extended to Facebook; apps.facebook.com would redirect to www.facebook.com only if the user was logged in.

I also looked into detecting the current logged in Facebook user by loading a page that would redirect to their user page on a domain that was not whitelisted. I expected it to send back the URL that broke the CSP, but the specification specifically states it sends back only the domain name. At this point, I wasn’t sure what to do with this exploit. It was clear that it was something I didn't want on the internet, so I did the only thing I could think of doing: reporting the exploits in Google and Facebook to Google and Facebook.

Communing with the Spirits

Google was the first to reply, and they asked for details of how this could be used against a Google user. I replied that such an exploit could be used to create a Google ‘pay wall’ that requires users to +1 on Google Plus before reading an article. I also proposed that it could be used to stage more believable phishing attacks, as users don’t expect third parties to know if they were logged into Google. The last portion of my reply asked for help in handling the widespread nature of the exploit.

After some time, Google replied and told me that an internal discussion had been had concerning the exploit and that nothing would be done about it.

Detecting who is Logged in

Even if the problem wasn't recognised to be of severity enough to attempt to mitigate it, I knew that something more could be done through CSP abuse. What especially caught my attention was that the domain name of the site that broke CSP was reported back to my server. I concluded that if a web service would redirect to a (sub)domain that indicates something secret about the user, it would be a serious exploit.

What I expected to find was an endpoint such as '/me' that you commonly find on services hosting user generated content that would refer to a sub-domain owned by that user, for example ‘zemnmez.github.io’. In my search I found nothing on a Google domain, but I read further into the definition of CSP directives and noticed that though domains were accepted, paths were also accepted, which opened up whole new avenues of investigation.

What I realised was that what CSP abuse allowed me to do was to allow me to make assertions about redirection and use the results of those assertions to determine information about the user. This allows us to assert that the current logged in user is a given user, or more generally that a user has access to specific admin panels – whether the user does or does not have super user privileges to something on the site in the literal sense.

Detecting Barack Obama

Obviously, being in the position the eminent President of the United States is, I doubt he is logged in personally to Facebook all of the time, but many people are. Similar exploits to this apply to every website I tested that you could reasonably expect to have logins. By using CSP to whitelist https://facebook.com/me and https://facebook.com/barackobama and embedding 'http://facebook.com/me' as an image, I can conditionally create a CSP report only if the current user on Facebook is not Barack Obama.

This proved to be a success (in detecting myself, rather than Barack Obama, I didn’t have him on board to test this) which made me much more worried about the consequences of the exploit. Rather than being able to just tell what websites you were currently logged in to, I could also now tell, within constraints, who you were logged in as on those websites.

Something like this could easily be used to work out who the user visiting your website was with just a little investigative work, but in addition information about their browsing habits and the powers they had on those sites. Beyond that, it's probably possible to detect things such as if you are currently logged into your bank and are performing a specific action, or are capable of performing a specific action because redirect-on-fail is such a common pattern.

This made me all the more worried, so I reported the exploit to the internet, and opened another bug with Google, this time concerning disclosure of current login on Google Plus.

Closure

Facebook wrote back to me and said that it was an interesting exploit, asking if there was some way to fix the redirect problem. I explained to them that yes, it could be fixed, but not in any good way– the only way being to not use ‘Location’ based redirect headers. I mentioned also that I had realised that it had greater connotations than I originally thought, and that I had reported it to the internet bug bounty program.

Google got back to me and explained that the possibility of exploits of this nature had been already brought up by one of their engineers on a W3C mailing list, and they had internally discussed the information leak problems associated with CSP and had come up with no solutions that did not hamper CSP's function.

I sent this information to Facebook, adding that I could give details of how Facebook logins could be detected, asking their thoughts on writing up what could be accomplished by manipulating CSP. Both Facebook and Google told me that it was not significant enough to warrant a fix, and additionally that writing it up would be a good idea. The internet bug bounty program has not replied.

Closing Remarks

This exploit allows in essence the ability to glean the result of a conditional redirect and additionally the destination domain of that redirect. Information leaks are present wherever the redirection of a user depends on conditional information that might be important and also where the domain the user is redirected to is important.

The only way to prevent it is, as far as I know not to use ‘Location’ based redirects.

Zemnmez

Monday 7 July 2014