giovedì 23 febbraio 2017

A tale about Appengine's authentication and life

Hello everybody. My name is Andrey Shevchenko, and for the past three years I've been involved in the world of Whitehat security research. Never made a blog because, who would read it? But this time it seems that people are interested in something I've found (and apparently someone else before me), and Eduardo himself asked me if I was interested in writing something. So, here it goes:

Google has this cute little subdomain called appengine.google.com. In the old days it used to have a site attached to it as well, but it's been shutdown in favor of Google Cloud. Anyway, right now the only function that this subdomain has is to authenticate users on third party domains. Except for some reason one subdomain on Google itself.

To summarize, here are the sites that use this authentication:
  • Anything on a .withgoogle.com domain, including the bug hunter dashboard
  • enterprise.google.com, which is some sort of administration panel for Gsuite accounts and even Google Partners
  • .appspot.com sites, which are user generated, I think.
The way it works is:
  • ServiceLogin on accounts.google.com redirects you to appengine.google.com/_ah/conflogin, appending an "auth" token to it, as well as a continue parameter that is predefined.
  • Conflogin redirects you to that continue parameter, with a state token added to it.
  • The destination site generates an authentication cookie based on that state token, and you're logged in.
This procedure has one major weakness, after the ServiceLogin, the entire login chain can be done with the Cookie header completely removed. All you need are the URL tokens. Another weakness is that if the victim is logged into multiple accounts, at some point it asks which user you want to authenticate as, which means that there's now a Referrer header containing, depending on which site you're logging into, either the auth or the state token (more on that later).



These two weaknesses mean that an open redirect anywhere in this redirect chain would allow an attacker to steal a token which can then be used to reauthenticate, even if the user completed the chain successfully.

At first, since I was focusing on enterprise.google.com, I tried to look for open redirects there. It didn't work, since the only potential redirect on that site was the logout, and for some reason it disregarded any continue parameter you gave it. Even if it didn't, it might have still not worked because the logout could invalidate the previous token.
I was exploring this in late November. After that, extremely difficult life circumstances meant that I couldn't physically work on it for a full month, and I was not in a good mental state to do that anyway.

When I got back to it, I suddenly realized that I could exploit appengine itself to do the open redirect for me. The key was in the continue parameter on conflogin, which had a few quirks:
  • If the domain on the parameter was appengine.google.com, it would trigger the "choose account" page right away, which meant that the Referrer contained the auth token.
  • If the domain was anything else, be it enterprise.google.com or facebook.com, it would always just 302 redirect to that page, adding a state token. So the conflogin page itself had an open redirect, but the state token was useless in that case, and since there was no confirmation page first, it didn't leak the auth.
  • If conflogin didn't receive a valid auth token, it would just throw a 500 error, no redirect for you.
This led me to craft a special exploit link: 
https://appengine.google.com/_ah/conflogin?continue=https%3A%2F%2Fappengine.google.com%2F_ah%2Fconflogin%3Fcontinue%3Dhttps%3A%2F%2Fwww.facebook.com%26auth%3DIQT_6z_Sm1qPHFDThpgOiB4TfVwVGVn6XCZ-5rQan1p3b6hdSD3diduF888FG6JRrC_wMg.&pli=1&auth=IQTsrZcGTL4q6YcJoIwX0IrHYVujhQVqVReXiknaJMQWg5Z09VGEDThy_P9xXD3mN5aIoA.

I highlighed the main features. Now in truth this is the second step of the exploit, what ServiceLogin redirects to. The green auth token is the one that has to be stolen. As you can see the first continue parameter points to the exact same page. This means that the "choose account" page is triggered right here, and the Referrer contains the green token. After clicking "next", the user is redirected to another conflogin page pointing to facebook.com (to show that it can be any URL) with an already filled auth token (highlighed in red), required to make the open redirect work. It's irrelevant whose token it is, it just needs to be valid.
It does however mean that the exploit is somewhat weak, because the victim must first be routed to an attacker-controlled site so that it would redirect with the correct parameters. But since any real attacker would use a URL shortener like goo.gl anyway, it's not as bad.




So, that's the bug. The attacker can then use the green token to authenticate to any of the aforementioned sites, including a google.com subdomain, since it doesn't check for cookies. With the right victim, the information leaked could be pretty devastating. The email addresses that the victim is logged into are also leaked, regardless of the site you're targeting.

Now the bug is fixed, the Referrer is stripped before any further redirecting is done.

I submitted this on the 27th of December, 9 days after the other guy. Had things been less turbulent for me, I would've probably submitted it earlier and gotten the bounty, but such is life I guess. Congrats to him nevertheless.