1

I'm reading about Google OAuth and implicit flow. In Google docs it says that the access token received using the implicit flow must be validated otherwise the application might be vulnerable to "confused deputy problem." (https://developers.google.com/accounts/docs/OAuth2UserAgent#validatetoken)

I was wondering if someone could come up with an example which would demonstrate the vulnerability? Let's say we have Alice who is a regular user. If some adversary presents his own token (assuming that this token can only access adversary's service - i.e. Google Drive) I don't see how adversary could cause any damage. His own token will only work with his Gdrive - so Alice's files could not be affected with this.

I'm sure there's a good reason for verification but can't think of one... Ideas?

markovuksanovic
  • 231
  • 1
  • 10
  • I believe they're looking at preventing phishing type attacks. If tokens aren't validated client side, then a malicious server acting like Google Drive could potentially trick you into uploading files to the adversaries server rather than Google Drive itself. Tokens should also always be validated server side, so as to prevent blindly accepting any token given as the person it claims to be. – RoraΖ Aug 25 '14 at 13:10

3 Answers3

3

I believe that the following example demonstrates the problem (based on the accepted answer from https://stackoverflow.com/questions/17241771/how-and-why-is-google-oauth-token-validation-performed)

All of this assumes the use of the OAuth Implicit Flow

  1. Alice connects her browser to GoodApp.com
  2. GoodApp.com obtains an OAuth access token authorized by Alice.

    A) This access token is tied to Alice’s identity at the Authorization Server.

    B) The access token is either used by GoodApp.com to authenticate Alice or to access
    some OAuth resource on behalf of Alice.

  3. Alice connects her browser to BadApp.com (for whatever reason; let’s say that BadApp.com "offers games that look kind of fun")
  4. BadApp.com obtains an OAuth access token authorized by Alice.
  5. BadGuy (who controls BadApp.com) then connect’s his browser to BadApp.com, and gets BadApp.com to redirect BadGuy’s browser to GoodApp.com with a spoofed OAuth authorization response that includes the access token that BadApp.com has for Alice.
  6. If GoodApp.com accepts the spoofed response, then BadGuy can act as Alice as follows.

    A) If the access token is used by GoodApp.com to authenticate Alice, then BadGuy can do anything Alice could do at GoodApp.com

    B) If the access token is used by GoodApp.com to access some OAuth resource, then BadGuy can cause GoodApp.com to do anything within the “scope” of the access token, all on behalf of Alice.

Therefore, if GoodApp.com verifies that any received access token was indeed intended for itself, then it can avoid the bad things as described in the example above.

Note that I believe an OAuth Client's proper use of the "state" parameter for cross site request forgery can also mitigate this problem, independently from access token validation.

1

I think the best way to understand how this pattern of OAuth use can be insecure is by talking about the purpose of OAuth scopes.

According to its design, an OAuth scope represents a set of possible actions that can be performed on behalf of the authenticated user. So (as a made-up example) if your client gets a token scope with the "send_messages" scope, then it can send messages on behalf of the user. In some sense, the true definition of a scope is what actions a token with that scope lets you perform.

The problem with the way "Login with FB/Twitter/etc." is implemented is that they all use a single scope (e.g. "public_profile" for Facebook).

According to the documentation, this scope is pretty harmless - with this the client can view the identity of the current user. However, if a third-party website A.com uses this token to check a user's identity and log them in to A.com, they have essentially expanded the definition of the public_profile scope to mean "view public profile information, and also access this user's resources on A.com".

All you need at this point is for an attacker to get a token with a public_profile scope (for example, by running another website with a "Log in with Facebook" link) - this requested scope seems harmless according to Facebook's documentation and what they show the user, but in reality if the attacker can pass that to A.com, they can access the user's resources.

The solution

The solution that has emerged is for A.com to verify that the token was generated specifically for A.com - that is, that during the OAuth login flow, the user was directed back to A.com instead of another site.

To do this, the generated OAuth token has extra information associated with it, specifically "which website/application was this token sent to". The presence of this extra information determines the result when you inspect the token (e.g. the /debug_token endpoint).

(I personally think this more or less constitutes a "invisible scope", and we wouldn't have this confusion if Facebook/etc. had provided custom third-party login scopes, e.g. "third-party:a.com" - however, the existing solution is just as functional.)

(The "implicit" flow of OAuth sometimes gets wholly blamed in this situation, which I think is missing half the point. The issue is that the "implicit" flow allows an attacker to insert their own OAuth tokens by intercepting the browser's redirect, but this would not be a problem if the OAuth scopes were not being redefined.)

cloudfeet
  • 2,528
  • 17
  • 22
0

Cross-site request forgery, which is the problem you've described in your question, is slightly different from a more general confused deputy problem which is described in the other answer. CSRF involves the attacker's token, not Alice's (using the same example as before). And yes, CSRF can be mitigated by leveraging the state parameter.

But a different example of confused deputy problem, as described in the other answer, isn't as simply resolved. Instead, the authorization server would need to validate each API call against the client_id and access token (w/ scopes)

akoo1010
  • 51
  • 2