Hacker News new | past | comments | ask | show | jobs | submit login
Achilles Heel of OAuth or Why Facebook Adds #_=_ (homakov.blogspot.com)
113 points by homakov on March 15, 2013 | hide | past | favorite | 33 comments



The OAuth Spec actually does address white listing redirect_uri's. This threat is discussed in section 4.1.5 of the OAuth 2.0 spec here: http://tools.ietf.org/html/draft-ietf-oauth-v2-threatmodel-0...

Oddly, Facebook has chosen not to follow this recommendation. So any websites that integrate Facebook OAuth must ensure that they contain no open-redirects or they can be hacked in this way. This is worrisome because open-redirects would not otherwise be considered much of a security problem.


Hopefully not too oddly: Facebook was one of the first OAuth 2.0 implementations and the additional benefits of requiring stricter pre-registration was not initially apparent. An unfortunate oversight. For kicks: compare section 5.2.3.5 v00 with v01

Changing the implementation at this point is a daunting task (for both Facebook and our developers) but we do hope to offer it as part of a future migration.


Interesting. I didn't know that detail but it explains a lot. Hopefully it won't be too long until you address this!


> This is worrisome because open-redirects would not otherwise be considered much of a security problem

yeah, indeed. It becomes a problem for OAuth only. And, wait, Facebook is pwned, so it's he who MUST worry, not clients

Spec is very long and has many interesting discussions but have a look at real world. neither facebook nor twitter whitelist redirect_uri


I am sorry but I still miss something.

And, I read the OAUth2 spec again http://tools.ietf.org/pdf/draft-ietf-oauth-v2-26.pdf

* Why is there an access_token in a browser url ? (query string or fragment)

The access_token is provided by the Authorization Server to the client, and not to the user.

The user should only received an authorization_code. And, to get an access_token, the client must have an authorization_code and know the "client_secret".

access_token should never been seen on a browser, right ?

Does Facebook really respect the protocol? in other word, is it a facebook problem or an OAuth problem ?


you just raised another problem haha. response_type.

it's also flexible. Even if app 99.99% of time uses response_type=code someday hacker comes and usues token on hacked redirect_uri.

simply speaking response_type is also should be static and constant. But, gosh, let's fix first-world-problem first


It's exactly what I missed.

Thanks!


To me it seem hyperbolic to call it the "Achilles heel of OAuth [2.0]." Other oauth providers than Facebook are smart enough to make the redirect_uri constant. Then the attack surface is reduced from the whole of mydomain.com to mydomain.com/whatever-redirect_uri-is. For those, the attack needs to be sophisticated enough to interfere with that specific url. But if the client site is owned that hard, it's lost anyway.


client credentials threat is OAuth1 too.


Right, but other oauth2 providers than facebook aren't vulnerable to the redirect_uri hack you are describing, are they?


not sure, i didn't check all of them

also facebook is 90% of oauth


I'm not sure if I understand this problem or security hole here. When I write some OAuth application I need to register my redirect_url. So how somebody can steal access token / code?


If I understood, it works like this:

1. You register foo.com as your redirect with FB. Your oauth endpoint is actually foo.com/fbauth, but Facebook is OK with just the domain.

2. Somewhere else on your site, you allow open redirects, like maybe a user can create a link that you proxy with a redirect for click-tracking purposes, like foo.com/links?url=evil.com

3. An attacker makes an oauth query to Facebook with the redirect URL hacked so that it points at foo.com/links?url=evil.com

4. FB dutifully sends your user to the hacked URL, which redirects to evil.com with all of its hashy stuff in place.

5. Javascript on evil.com reads the hash and uploads it

It's not clear--and I'm too lazy to test--whether FB will restrict the forward to foo.com/fbauth if you're explicit about it when configuring your app. But certainly the wording on the developer console just asks for your site URL, and even though I'm pretty familiar with oauth, I have never bothered to do more than that. Google, on the other hand, forces you to.


Thanks for explanation. May I ask how the attacker can make "an oauth query to Facebook with the redirect URL hacked so that it points at foo.com/links?url=evil.com"? Are you saying that attacker somehow convinces user to visit maliciously created Facebook authentication URL?


Right, I worded that poorly. You need some other vulnerability for the attacker to pull this trick off. But, like homokov says, there are a lot of possibilities for that. Obviously, such a vulnerability is bad on its own and the site owner should prevent it, but FB should be better about mitigating it from their end.


not precisely visit, any CSRF technique can be useful. <iframe, window.open


you register not full path+query, only domain. Every website has huge attack surface


Sorry if I misunderstand, but would that mean that (along with what you wrote about whitelist/static) a "replace hash values", for instance, would mitigate the attack?

I currently have a OAuth (1.0a) implementation down the road (and would be very willing to hiring you when we begin). Am I understanding this correctly that a "good" practice would be to redirect the user always to e.g. a static "you've granted app X permissions", or other dummy page (within our domains control) which the user will simply close, or oob?

Not asking you to dish out your expertise, just a quick question :) And thanks for the nice articles, you're doing a lot of good.


1.a does not implement Implicit flow (sending token #token=..)

sending #_=_ is only protection of facebook open redirect, it's impossible to do same on every possible open redirector on the client's website.

by static I mean exact value of path+query


Can someone explain to me why the access code is sent back as the hash in the url not the query string?


because query string is available in document.referrer on external websites.

hash is supposed to be more secure - not sent on server side.

but with 302 redirects it's not so secure.


But this is only for JavaScript clients, right? I believe all the OAuth APIs I've consumed from Python send access_token in the query string.


Maybe you are thinking of the code parameter? The one that can be exchanged for an access token in a server-to-server request?


I believe they're both in the query string, but you're right - code is what's sent by way of the client. access_token is exchanged between the servers.


what provider? Facebook never sends it in query string. It can also be available for Man In The Middle, in server side logs etc. Hash is supposed to be more secure.


FB definitely sends access token via URL param for the server side flow: https://developers.facebook.com/docs/howtos/login/server-sid...

If there were a mitm they could get it even if it's in the hash. It has to travel to the client at some point.


if it's in hash it can be seen only from FB response (https). redirect_uri can be http so hash is not transferred

of course it's visible in server-2-server, but not client-server


For those who are totally confused as to why an access token is being shared with an end user and why it's transmitted in a URL fragment, I think I figured out what's going on. Facebook appears to have a flow for logging in client-side in the browser [1]. In that flow, the access token is meant to be delivered to a JavaScript client in the browser, so a URL fragment makes some sense.

I don't know if any of this is covered by the OAuth spec. (I'm only familiar with the so-called "three-legged" OAuth protocol.)

[1] https://developers.facebook.com/docs/howtos/login/client-sid...


response_type is also flexible,

but spec says explicitely to avoid Implicit flow


I don't quite get the "let me explain again response_type=code flow". Doesn't seem relevant to the article since the code flow isn't leaking any access token to the client side at all. Though the solution of making the redirect_uri explicit seems pretty good for the original problem.


it is relevant — for Stolen Credentials threat.

if you have creds you can obtain access token for ANY redirect_uri, even for leaking. if it would be static it would not be possible to leak it at all


I don't understand what they expect them to do? Drop their entire current system and build a new one?

What alternatives are their?


This guy is on a role!




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: