Facebook doesn't care about your privacy, but you should. Facebook implements OAuth2 - readers of my blog know how shitty OAuth2 is and how awesome OAuth2.a will be.
Apps actually cannot require permissions ('scope' param). They propose it, but you can choose them - update authorization URL.
Example - you are redirected to:
https://www.facebook.com/dialog/oauth?client_id=130409810307796&redirect_uri=http%3A%2F%2Fapps.facebook.com%2Ftetris_battle%2F%2F%3Fkt_track_apa%3D1%26reload%3D1%26reloadTime%3D1346239416%26localJS%3Dfalse&state=6997cb601838cb0fb65d53aecbebcd21&scope=publish_actions%2Cemail%2Cuser_location%2Cuser_birthday
Just change 'scope' param
https://www.facebook.com/dialog/oauth?client_id=130409810307796&redirect_uri=http%3A%2F%2Fapps.facebook.com%2Ftetris_battle%2F%2F%3Fkt_track_apa%3D1%26reload%3D1%26reloadTime%3D1346239416%26localJS%3Dfalse&state=6997cb601838cb0fb65d53aecbebcd21&scope=
And authorize the app. You permitted nothing special but app works - enjoy.
UPDATE:
The post had nothing to do with security. I was annoyed with terrible fact "you can ask permissions, it will look legit and user cannot uncheck them in UI. Well if he's smart enough to change URL - you have to check permissions in your code"
There are two ways to fix it (OAuth2.a deals with the issue this way):
1) when app has "frozen" scope. This is not param in URL anymore, just a field in the database. Developer doesn't need to make sure what is allowed anymore - he is sure.
2) when app has "agile" scope. Client 'proposes' scope and User can uncheck not desired permissions. App should check explicitly what was permitted.
Wednesday, August 29, 2012
Tuesday, August 28, 2012
OAuth2: One access_token To Rule Them All
One access_token to rule them all...
I demonstrated The Most Common OAuth2 Vulnerability in Authorization Code Flow a while ago – signing in the Victim's account(followed by getting an access to Victim's resources on that website) by connecting Attacker's oauth account through CSRF-callback URL with Attacker's code. Despite popularity of that attack, it can be easily mitigated with 'state' param(to prevent CSRF) – and now it's fixed in popular ruby/python libraries.
Now I want to share a very straightforward attack for Implicit Flow based websites(realized in brainstorming with @isciurus). There is no proper mitigation so far.
Generally speaking:
- 'access_token' is a string that identifies your Resources on Provider. No other parameters are required to call Provider's API. There is no guarantee user's access_token1 for client1 is not used by client2 or client75 - nothing stops them.
- Let's assume I create a website: e.g. superfunnypicturez.com. I ask my users to authorize my Client on facebook and I don't ask any scopes at all - I need only "/me" endpoint with "uid" param to be available. They authorize my Client because superfunnypicturez.com requires only 'read' access and nothing seems to be dangerous. I get their 'access_token's and now I can request /me endpoint and get their "uid"(often used for authentication)
- Let's assume there is another site: e.g. weuseimplicitflow.com and yep, it uses Implicit Flow(receives token via CALLBACK#access_token=123qwe...). It's a pity - this website authenticates users by given access_token. Most likely it sends access_token on server-side and invokes /me endpoint from there.
- Since I am admin of superfunnypicturez.com and you authorized my Client and gave me an access_token from your account I just put that access token in callback URL: CALLBACK#access_token=YOUR_TOKEN and now weuseimplicitflow.com's Client authenticates me as you because that token I just provided returns your 'uid' when /me endpoint is called. I need only one access_token from your Provider's account to rule all your accounts on 3rd party websites that use Implicit Flow.
Recap:
OAuth2 is extremely insecure for authentication goals by default.
- Auth Code Flow: You must use 'state' parameter and verify - is this user the same user you sent to authorization URL by checking state value from session and returned one.
- Implicit Flow: You must ensure that access_token you are going to use is issued for your Client. Please, use this URL for Facebook: https://graph.facebook.com/app?fields=id&access_token=TOKEN. Not all providers support this feature though. If access_token is anyhow obtained from User (not from Provider) - you must verify is this access_token issued for your Client.
Oh, also:
As I mentioned in my previous post on stupidity of OAuth2 - if Provider has Implicit Flow as an option - lots of Users can be compromised someday. If a single XSS is found on Client's domain - hackers can steal all access_tokens with it even if your website uses Auth Code Flow by just changing response_type param in authorize URL.
Author of this article is awesome - you can actually hire him.
Wednesday, August 1, 2012
SaferWeb: OAuth2.a or Let's Just Fix It
Eran and others, chill out. We should stop whining to nobody. I prefer rather "we gotta fix this, this and discuss that" than "it is bad"-attitude. Some people were surprised because they like OAuth2.
What about me? I was not surprised because OAuth2 is far from perfect. But there is no reason to give up, it's in our hands. ( By the way I'm waiting for comments on Hacker News OK?)
Below I explain some security and usability concerns about current OAuth2 and propose(I do, not just say 'it is bad') improvements to make it more agile and safe-by-default. OAuth2.a is going to be easier to implement and more secure.
What about me? I was not surprised because OAuth2 is far from perfect. But there is no reason to give up, it's in our hands. ( By the way I'm waiting for comments on Hacker News OK?)
Below I explain some security and usability concerns about current OAuth2 and propose(I do, not just say 'it is bad') improvements to make it more agile and safe-by-default. OAuth2.a is going to be easier to implement and more secure.
TL;DR:
- redirect_uri can be on any domain and amount of redirect_uri-s is unlimited. They are whitelisted and only exact match verification is applied(redirect_uri IS NOT flexible domain.com/*). Client sets redirect_uri-s on his admin page in Provider.
- for every redirect_uri MUST be defined certain response_type - token or code. It must not be possible to set response_type in authorize URL. Every redirect_uri has its own defined response_type
- Most Common OAuth2 CSRF Vulnerability from my previous post. We should either introduce a new *compulsory* param(e.g. csrf_token) or just raise awareness about the issue.
- We need either assign 'scope' to certain redirect_uri as well as response_type(it MUST not be in URL) or allow user to choose what parts of scope to allow. It's up to Provider's implementation.
- We should introduce 'mass refreshing' of access_token-s. Client sends an array of refresh_token-s and client's credentials and get's hash with refresh_token=>access token.
- We need to define some DEFAULT URL paths and error codes to add a little bit more "interoperability". Really, is it so damn hard to keep your endpoints and error codes similar to other services?