Looks like I'm late to the "last call".  The following is old business, but I 
can't find any replies to it, and I think it's a bigger issue than I thought it 
was then.

Briefly: The protocol breaks if the "state" parameter is guessable.  An 
attacker can cause the user to access the attacker's resource when the user's 
expects to access the user's resource, if the attacker's timing is lucky and he 
guesses a state.  The protocol breaks in the same way if redirect_uri's are 
guessable and they are not checked, since the reason you'd want to vary a 
redirect_uri is to incorporate a state into it.

The spec says that the state is an "opaque value" (page 15 of 
draft-ieft-oauth-v2-13).  If opaque values are unguessable, then I'm not 
finding fault with the part of the spec about handling states.  Searching 
Google for a consensus on the meaning of "opaque value" doesn't seem to give 
much clarity on whether a value guessable by an adversary might be considered 
opaque.  Wikipedia's page on "opaque data type" seems to only say it's 
uninterpreted, not that it's unguessable by an adversary.  For example, if the 
spec permits an implementor of a client to use the integers 1,2,3,... 
consecutively when the protocol calls for an "opaque value" for the state, 
where the opaqueness means that the auth server doesn't know or care what those 
integers mean, then the protocol is insecure and the spec is broken.  The 
scenario for losing is below, but first I want to give credit to Torsten since 
I'm basically agreeing with him:

(Beginning of the scenario where we can lose if the redirect_uri is guessable)

From: Freeman, Tim [mailto:tim.free...@hp.com]
Sent: Tuesday, September 14, 2010 11:03 AM
> After some thought, I think I see the real problem with omitting the check on
> redirect_uri [when fetching the access token].   Without the check, the 
> following
> can happen:

(Oops, I left out the "when fetching the access token" part in the Sep. 14 2010 
email.  Torsten found the right interpretation in context, but that context 
isn't present in this email so I have to correct here.  I went on then to 
describe how the protocol loses if the parts of the redirect_uri that are not 
checked when fetching the access token are guessable.  I'm repeating that 
scenario immediately below.)

> 1. Evil user starts OAuth flow on the client using the web-server flow, using
>    a hacked web browser.
> 2. The hacked web browser does the normal thing in the flow, requesting the
>    evil user's username and password, and at the end the hacked browser is
>    given a redirect like:
>
>     https://www.goodclient.com/oauth/evilUserAcct?code=evilAuthCode
>
>    The hacked browser saves evilAuthCode and does not perform the redirect.
> 3. Suppose the evil user's web site can persuade a known victim user with
>    a normal browser to visit goodclient's web site and do OAuth.  The victim's
>    user id on the client is public knowledge, and the evil user's web site
>    persuaded the victim to start OAuth at a known time, so it can guess when
>    the victim will complete the OAuth exchange.  Before then, the evil web 
> site can visit
>
>     https://www.goodclient.com/oauth/victimUserAcct?code=evilAuthCode
>
>    which is likely to leave the client associating the victim's user id with 
> an access
>    token that accesses resources controlled by the evil user.

From: Torsten Lodderstedt [mailto:tors...@lodderstedt.net]
Sent: Wednesday, January 26, 2011 1:22 PM
> Your assumptions is the attacker is able to predict the way the victim's
> session with the client is represented. I would consider that as a
> security vulnerability of the client since this would also allow the
> attacker to take over the session on his own device.

Tim says now:
I agree that I'm assuming that the attacker can predict how the victim's 
session is represented.  So far as I can tell that's consistent with the spec, 
and it is a security vulnerability.  IMO the spec should say not to do that.

Tim said on Sep 14, 2010:
> Checking the redirect URI doesn't solve the problem in the case where the 
> user id on the client is encoded in the "state" opaque value instead of the 
> redirect URI.
>
> Saying "The authorization server SHOULD require the client to pre-register 
> their redirection URI" (page
> 17 of http://tools.ietf.org/html/draft-ietf-oauth-v2-10)

now page 11 of draft 13

> should have MUST instead of SHOULD, since it is important that we're really 
> redirecting to the client
> when we're distributing the authorization code by redirecting.

(End of the scenario where we can lose if the redirect_uri is guessable)

(Beginning of the scenario where we can lose if the state is guessable)

We can also illustrate the same problem with guessable state that we had above 
with a guessable redirect_uri.  I'm probably misspelling the URL's, but I'm 
sure it's clear anyway.  Suppose we have states that are guessable because they 
are successive integers.  Then the following can happen:

1. Evil user starts OAuth flow on the client using the web-server flow, using
   a hacked web browser.
2. The hacked web browser does the normal thing in the flow, requesting the
   evil user's username and password, and at the end the hacked browser is
   given a redirect like this that's supposed to go to the client to give it an 
auth code:

     https://www.goodclient.com/oauth?state=37&code=evilAuthCode

   The hacked browser saves evilAuthCode, guesses that the state to use on the 
victim
   is 37 + 1 = 38, and does not yet perform the redirect.
3. Suppose the evil user's web site can persuade a known victim user with
   a normal browser to visit goodclient's web site and do OAuth.  The evil 
user's
   web site persuaded the victim to start OAuth at a known time, so it can 
guess when
   the victim will complete the OAuth exchange.  Before then, the evil web site 
can visit

      https://www.goodclient.com/oauth?state=38&code=evilAuthCode

   which is likely to leave the client associating the victim's user id with an 
access
   token that accesses resources controlled by the evil user.

(End of the scenario where we can lose if the state is guessable)

If you believe these scenarios, I recommend the following fixes:

* Require states to be unguessable.
* Require clients to register all components of the redirect_uri's when they 
get their client credentials.
* Since the redirect_uri is a function of the client id, we can drop it from 
the protocol, and the issue of when to check it and why goes away.  If you want 
backward compatibility with people who implemented earlier revisions of the 
spec, ignore any redirect_uri's that are offered to the auth server.
* Require clients to use the state to keep concurrent users distinct, not 
tweaks to redirect_uri's.

There is an existing argument against getting rid of the redirect_uri's, stated 
by Torsten perhaps among others:

From: Torsten Lodderstedt [mailto:tors...@lodderstedt.net]
Sent: Wednesday, January 26, 2011 1:22 PM
> [Specifying redirect_uri's at client registration time] might not scale in 
> some
> deployments (manual process) or require dynamic client registration (not
> specified yet). With the lack of dynamic client registration, it only
> works for clients bound to certain deployments at
> development/configuration time. As soon as dynamic resource server
> discovery gets involved, that's no longer feasable.

I don't see how clients get credentials by a path that does not allow them to 
register a redirect_uri at that time.  Somehow the auth server knows that the 
client is legitimate.  Why can't the correct redirect_uri to use for the client 
be learned by the same path?  If dynamic resource server discovery is 
important, can you give a concrete use case for it?  (I haven't recently read 
the use cases document.  For all I know it may be in there already.  I also 
have 613 unread emails in my "Oauth" folder, maybe it's in there.  If so, my 
apologies, but realistically I will need a pointer to the existing document or 
conversation if I'm going to read it any time soon.)

In any case, this clause in the spec seems likely to greatly reduce the 
probability of secure implementations (draft 13, page 12):
>   The authorization server SHOULD require the client to pre-register
>   their redirection URI or at least certain components such as the
>   scheme, host, port and path.  If a redirection URI was registered,
>   the authorization server MUST compare any redirection URI received at
>   the authorization endpoint with the registered URI.

If only some components of the redirect_uri are preregistered, I suppose the 
auth server is only comparing those components, since it can't compare 
components with a correct value that it doesn't know.  Unless it is obvious to 
everybody that my arguments above are meritless, we have not yet figured out 
the security considerations of registering or not registering the redirect_uri, 
much less registering only some components of the redirect_uri.  If we can't 
easily figure it out, it is not likely that nearly all implementors of the spec 
are going to figure it out correctly.  Thus this vagueness is going to lead to 
a lot of insecure OAuth 2 implementations.  We should figure out which checks 
have desirable security consequences and specify that exactly those checks are 
performed, not leave it up to each implementor to correctly figure out on their 
own.

Finally we have this comment from Thorsten that has me confused.  Tim said:
> Saying "The authorization server SHOULD require the client to pre-register
> their redirection URI" (page 17 of 
> http://tools.ietf.org/html/draft-ietf-oauth-v2-10)
> should have MUST instead of SHOULD, since it is important that we're really
> redirecting to the client when we're distributing the authorization code by 
> redirecting.

and then Thorsten said:
> See above. From a security perspective this is clearly a good option.
> From an architectural and operational point of view, I would consider
> this to restrictive.

On the face of it you seem to be saying that every available option is either 
insecure or inoperable.  We need things to be both secure and operable, so that 
seems to imply that there is no good path forward.  I am not surprised to see 
diagreement on whether a specific solution is secure, or operable, but I didn't 
expect to see someone claim there are no good solutions at all.  Do you see any 
good alternatives?

Tim Freeman
Email: tim.free...@hp.com
Desk in Palo Alto: (650) 857-2581
Home: (408) 774-1298
Cell: (408) 348-7536


-----Original Message-----
From: Torsten Lodderstedt [mailto:tors...@lodderstedt.net]
Sent: Wednesday, January 26, 2011 1:22 PM
To: Freeman, Tim
Cc: Eran Hammer-Lahav; oauth@ietf.org
Subject: Re: [OAUTH-WG] Why give the redirect URI when trading an 
[authorization] code for an access token?

Hi Tim,
> From: Eran Hammer-Lahav [mailto:e...@hueniverse.com]
>> 1. Evil user starts the OAuth flow on the client using the web-server flow.
>> 2. Client redirects the evil user to the authorization server, including 
>> state
>> information about the evil user account on the client.
>> 3. Evil user takes the authorization endpoint URI and changes the
>> redirection to its own site.
>> 4. Evil user tricks victim user to click on the link and authorize access
>> (phishing or other social engineering attack).
>> 5. Victim user thinking this is a valid authorization request, authorizes
>> access.
>> 6. Authorization server sends victim user back to the client, but since the
>> redirection URI was changed, back to the evil user site.
> and the rest of the steps were revised to:
>
>> 7. Evil user takes the code and gives it back to the client by
>> constructing the original correct redirection URI.
>> 8. Client exchanges the code for access token, attaching it to the evil 
>> user's account.
>> 9. Evil user can now access victim user data on his client account.
> Step 6 requires the authorization server to redirect the victim user's 
> browser to the evil user's site, which will only happen if the authorization 
> server does not check the redirect URI when returning an authorization code.  
> That check is required by OAuth 2, and isn't the check that I'm questioning.

The authorization server either checks the actual redirect_uri against a
pre-configured uri (step 4) and it checks the actual redirect_uri in
step 8.

The first check immediately detects attempts to acquire end-user
authorization under the identity of a legimitate client. That's fine as
long as the authorization server really forces all clients to
pre-register redirect_uri's. That approach might not scale in some
deployments (manual process) or require dynamic client registration (not
specified yet). With the lack of dynamic client registration, it only
works for clients bound to certain deployments at
development/configuration time. As soon as dynamic resource server
discovery gets involved, that's no longer feasable.

The later check detects different uri's used for the end-user
authorization process and the token issuance. That's the characteristics
of a session fixation attack since the attacker MUST use another
redirect_uri in steps 2 and 4. Otherwise it does not get access to the
authorization code of the victim. This approach has the drawback that
the redirect_uri must be associated with the authorization code but it
works for all kinds of deployments and anonymous clients.

> In contrast, I was proposing that the authorization server not check the 
> redirect URI when it returns an access token.  Since, in the absence of such 
> a check, the redirect URI is neither checked nor used to compute the result 
> of the query, I was proposing that we drop the redirect URL from that step of 
> the protocol altogether.
>
> I misspoke in the subject line of the email that started this thread, so I 
> just now changed "access code" there to "authorization code".  We have access 
> tokens and authorization codes, but not authorization tokens or access codes.
>
> After some thought, I think I see the real problem with omitting the check on 
> redirect_uri.   Without the check, the following can happen:
>
> 1. Evil user starts OAuth flow on the client using the web-server flow, using 
> a hacked web browser.
> 2. The hacked web browser does the normal thing in the flow, requesting the 
> evil user's username and password, and at the end the hacked browser is given 
> a redirect like:
>
>     https://www.goodclient.com/oauth/evilUserAcct?code=evilAuthCode
>
> The hacked browser saves evilAuthCode and does not perform the redirect.
> 3. Suppose the evil user's web site can persuade a known victim user with a 
> normal browser to visit goodclient's web site and do OAuth.  The victim's 
> user id on the client is public knowledge, and the evil user's web site 
> persuaded the victim to start OAuth at a known time, so it can guess when the 
> victim will complete the OAuth exchange.  Before then, the evil web site can 
> visit
>
>     https://www.goodclient.com/oauth/victimUserAcct?code=evilAuthCode
>
> which is likely to leave the client associating the victim's user id with an 
> access token that accesses resources controlled by the evil user.

Your assumptions is the attacker is able to predict the way the victim's
session with the client is represented. I would consider that as a
security vulnerability of the client since this would also allow the
attacker to take over the session on his own device.

> Checking the redirect URI doesn't solve the problem in the case where the 
> user id on the client is encoded in the "state" opaque value instead of the 
> redirect URI.
>
> Saying "The authorization server SHOULD require the client to pre-register 
> their redirection URI" (page 17 of 
> http://tools.ietf.org/html/draft-ietf-oauth-v2-10) should have MUST instead 
> of SHOULD, since it is important that we're really redirecting to the client 
> when we're distributing the authorization code by redirecting.

See above. From a security perspective this is clearly a good option.
 From an architectural and operational point of view, I would consider
this to restrictive.

regards,
Torsten.

>
> Writing the spec required thinking through these cases.  It would be helpful 
> if the use cases were added to the spec, so people don't have to rediscover 
> them, and errors in the use cases can be discovered and fixed rather than 
> being made repeatedly by each person rediscovering the use case.
>
> Tim Freeman
> Email: tim.free...@hp.com
> Desk in Palo Alto: (650) 857-2581
> Home: (408) 774-1298
> Cell: (408) 348-7536
>
>
> -----Original Message-----
> From: Eran Hammer-Lahav [mailto:e...@hueniverse.com]
> Sent: Saturday, September 11, 2010 7:59 AM
> To: Torsten Lodderstedt
> Cc: Freeman, Tim; oauth@ietf.org
> Subject: RE: [OAUTH-WG] Why give the redirect URI when trading an access code 
> for an access token?
>
> Sorry.
>
> 7. Evil user takes the code and gives it back to the client by constructing 
> the original correct redirection URI.
> 8. Client exchanges the code for access token, attaching it to the evil 
> user's account.
> 9. Evil user can now access victim user data on his client account.
>
> This is basically a session fixation attack.
>
> EHL
>
>> -----Original Message-----
>> From: Torsten Lodderstedt [mailto:tors...@lodderstedt.net]
>> Sent: Saturday, September 11, 2010 1:01 AM
>> To: Eran Hammer-Lahav
>> Cc: Freeman, Tim; oauth@ietf.org
>> Subject: Re: [OAUTH-WG] Why give the redirect URI when trading an access
>> code for an access token?
>>
>>    Doesn't step 7 require the evil user to know the client's secret?
>>
>> Am 10.09.2010 17:06, schrieb Eran Hammer-Lahav:
>>> 1. Evil user starts the OAuth flow on the client using the web-server flow.
>>> 2. Client redirects the evil user to the authorization server, including 
>>> state
>> information about the evil user account on the client.
>>> 3. Evil user takes the authorization endpoint URI and changes the
>> redirection to its own site.
>>> 4. Evil user tricks victim user to click on the link and authorize access
>> (phishing or other social engineering attack).
>>> 5. Victim user thinking this is a valid authorization request, authorizes
>> access.
>>> 6. Authorization server sends victim user back to the client, but since the
>> redirection URI was changed, back to the evil user site.
>>> 7. Evil user grabs the code and exchanges it for an access token.
>>>
>>> By checking that the callback URI used to deliver the code is the same as
>> the one used to initiate the flow, the authorization server can verify that 
>> the
>> user who initiated the flow is the same one to authorize access and finish 
>> the
>> flow.
>>> EHL
>>>
>>>> -----Original Message-----
>>>> From: oauth-boun...@ietf.org [mailto:oauth-boun...@ietf.org] On
>>>> Behalf Of Freeman, Tim
>>>> Sent: Wednesday, September 08, 2010 8:05 PM
>>>> To: oauth@ietf.org
>>>> Subject: [OAUTH-WG] Why give the redirect URI when trading an access
>>>> code for an access token?
>>>>
>>>> Hi.  I'm new here.  I searched the archives a bit and didn't
>>>> immediately find an answer to my question below.  My apologies if
>>>> there was some previous discussion of this that I missed.
>>>>
>>>> Looking at the draft spec at
>>>> http://tools.ietf.org/html/draft-ietf-oauth-v2-10,
>>>> I see in section 4.1.1 "Authorization code" on page 22 that it is
>>>> required to give the redirect_uri of the original request when
>>>> exchanging an authorization code for an access token, and the
>>>> authorization server must verify that the redirection URI is correct as 
>>>> well
>> as the authorization code.
>>>> Based on section 4.2 "Access Token Response" on page 25, it seems
>>>> that the redirect_uri is not used when constructing the response from
>>>> the authorization server.
>>>>
>>>> So far as I can tell, the redirect_uri is useless in this request.
>>>> It does not contain any secrets.  The authorization code is verified
>>>> and is meant to be an arbitrary unguessable identifier, so little is
>>>> gained by verifying the redirect_uri also.  It is not used to construct the
>> reply.  Why is it required?
>>>> Tim Freeman
>>>> Email: tim.free...@hp.com
>>>> Desk in Palo Alto: (650) 857-2581
>>>> Home: (408) 774-1298
>>>> Cell: (408) 348-7536
>>>>
>>>>
>>>> _______________________________________________
>>>> OAuth mailing list
>>>> OAuth@ietf.org
>>>> https://www.ietf.org/mailman/listinfo/oauth
>>> _______________________________________________
>>> OAuth mailing list
>>> OAuth@ietf.org
>>> https://www.ietf.org/mailman/listinfo/oauth
_______________________________________________
OAuth mailing list
OAuth@ietf.org
https://www.ietf.org/mailman/listinfo/oauth

Reply via email to