Subject: Re: [OAUTH-WG] Why give the redirect URI when trading an [authorization] code for an access token?

From: Eran Hammer-Lahav <[email-masked]>
Date: Tue, 25 Jan 2011 23:09:34 -0700

I found this in my archives as an open question. Can someone please review Tim's note and address the security considerations it contains?

EHL

> -----Original Message-----
> From: Freeman, Tim [mailto:[email-masked]]
> Sent: Tuesday, September 14, 2010 11:03 AM
> To: Eran Hammer-Lahav; Torsten Lodderstedt
> Cc: [email-masked]
> Subject: RE: [OAUTH-WG] Why give the redirect URI when trading an
> [authorization] code for an access token?
> 
> From: Eran Hammer-Lahav [mailto:[email-masked]]
> > 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.
> 
> 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.
> 
> 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.
> 
> 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: [email-masked]
> Desk in Palo Alto: (650) 857-2581
> Home: (408) 774-1298
> Cell: (408) 348-7536
> 
> 
> -----Original Message-----
> From: Eran Hammer-Lahav [mailto:[email-masked]]
> Sent: Saturday, September 11, 2010 7:59 AM
> To: Torsten Lodderstedt
> Cc: Freeman, Tim; [email-masked]
> 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:[email-masked]]
> > Sent: Saturday, September 11, 2010 1:01 AM
> > To: Eran Hammer-Lahav
> > Cc: Freeman, Tim; [email-masked]
> > 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: [email-masked] [mailto:[email-masked]] On
> > >> Behalf Of Freeman, Tim
> > >> Sent: Wednesday, September 08, 2010 8:05 PM
> > >> To: [email-masked]
> > >> 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: [email-masked]
> > >> Desk in Palo Alto: (650) 857-2581
> > >> Home: (408) 774-1298
> > >> Cell: (408) 348-7536
> > >>
> > >>
> > >> _______________________________________________
> > >> OAuth mailing list
> > >> [email-masked]
> > >> https://www.ietf.org/mailman/listinfo/oauth
> > > _______________________________________________
> > > OAuth mailing list
> > > [email-masked]
> > > https://www.ietf.org/mailman/listinfo/oauth

---

From: Torsten Lodderstedt <[email-masked]>
Date: Wed, 26 Jan 2011 22:22:26 +0100

Hi Tim,
>> 2. Client redirects the evil user to the authorization server, including state
>> 4. Evil user tricks victim user to click on the link and authorize access
>> 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
>> 8. Client exchanges the code for access token, attaching it to the evil user's 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:
>
> 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
>
> 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
> 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.
>> Subject: Re: [OAUTH-WG] Why give the redirect URI when trading an access
>>> 2. Client redirects the evil user to the authorization server, including state
>>> 4. Evil user tricks victim user to click on the link and authorize access
>>> 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
>>> 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
>>>
>>>> Subject: [OAUTH-WG] Why give the redirect URI when trading an access
>>>> authorization server must verify that the redirection URI is correct as well
>>>> that the redirect_uri is not used when constructing the response from
>>>> the authorization server.
>>>>
>>>> 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