We still have a problem with AT leaking. I think that needs to be dealt with
separately.
Access tokens should have a audience (by value or by introspection) the client
needs to tell the AS what resource it want s to use the token at and have that
included as the audience or the request rejected because it is an invalid
audience.
I have some concerns with requiring an audience for AT issuance. Today a
client can get a token with scopes "instantMessaging readMail sendMail
readContacts writeContacts" and then use that token against multiple
endpoints (im.example.com mail.example.com contacts.example.com). This
is a common usage of OAuth2.
Forcing the client to get a unique AT for each service it wants to talk
to is a change from the model that is currently in place.
Thanks,
George
On 2/23/16 6:17 PM, John Bradley wrote:
The idea of including the state in the PKCE calculation was one I think Hans
brought up at the meeting in Darmstadt.
I think we discounted it as not solving the problem because the attacker could
manipulate the code_challenge.
As and example the attacker receives the request and changes the code_challenge
to one it makes up based on the state from a second request made to the client
in it’s browser.
The attacker can replay the token to the client with the state that will
validate the code_callenge or use the token directly at the token endpoint to
get a access token as it would know both the client secret and code verifier.
We moved on to look at another way to validate state by passing it to the token
endpoint for validation to stop the cut and paste attack.
In thinking again about William and Nat’s question about why not PKCE, I looked
at the idea of using PKCE again.
The problem with using PKCE as it is now is that we made the assumption that
the attacker could not modify the request.
That got me trying to think of a way to:
a) stop the attacker from modifying the request (signed request, probably too
complicated to be generally deployed)
b) allow the client to detect if code_challenge has been modified and abort
of the request was compromise.
I realized that you could simply echo back the code_challenge from the
authorization endpoint and that would allow the client to know if
code_challenge had been altered in the request, assuming the attacker can’t
modify the response from the legitimate AS.
So if we add that step we now have a client where code_challenge can’t be
altered.
That in it selfs stops the cut and pate attack. It however still allows an
attacker to use the code it receives along with the the code_verifier and
client secret to get a AT and RT from the legitimate token endpoint.
So that is not enough Including state in the hash calculation helps against the
cut and paste attack but we fixed that by returning code_challenge.
That leaves the other things we were talking about returning from the
authorization endpoint.
If we include token_endpoint URI in the hash then any token the client requests
thinking it is for the attackers token endpoint won’t generate the same
code_challenge as the AS would based on it’s token endpoint. The attacker
would know the code_challenge and the real token endpoint URI but would have to
generate a collision in the lifetime of code to use the code. This would not
be possible based on the PKCE analysis.
Returning the code_challenge and including the token_endpoint URI in the hash
is the minimum needed for the code flow to stop both cut and paste as well as
protect the code from being used if stolen via a confused client attack. It
doesn’t stop the theft just the use of the token. So it is mitigating the
issue a different way from A and B that are trying to stop the attacker from
getting the code.
Given the technique I realized it would be simple enough to also include some
other paramaters in the hash
1) The authorization endpoint in the hash causing it not to validate if the
client has been given a bad authorization endpoint so the client can modify the
request.
2) The client_id so that it cannot be tampered with in the request.
3) The state This is tied to the browser instance for XSRF protection.
Including this means it cannot be changed and is another protection against cut
and paste.
Including all 4 in the hash may be overkill as they overlap in protection. I
however think that not integrity protecting one of the values might bite us in
the future.
We could go farther and include scopes or the whole request but that gets more
complicated than it is worth. We do have a option for request signing already.
So we almost had this at the Darmstadt meeting but it slipped away.
This is not stoping the attack it is protecting code.
I should point out that some of the attacks like man in the middling
registration can still compromise the client secret, making it possible for an
attacker to impersonate a client.
Nat’s option B doesn’t have a solution to that ether as far as I can tell.
I think the only option for that is to have a logical identifier for the AS and
some sort of discovery check at registration to be certain that you are using
the correct registration location.
Option A plus discovery works for that and mitigates confused client but not
cut and paste.
We still have a problem with AT leaking. I think that needs to be dealt with
separately.
Access tokens should have a audience (by value or by introspection) the client
needs to tell the AS what resource it want s to use the token at and have that
included as the audience or the request rejected because it is an invalid
audience.
That should happen at the token endpoint for code.
For implicit it would need to be at the authoriation endpoint and the audience
would need to be echoed back to prevent tampering.
The AT can also be protected by POP so I think that code and AT should be kept
separate issues.
John B.
On Feb 23, 2016, at 9:59 PM, Roland Hedberg <roland.hedb...@umu.se> wrote:
In line !
22 feb 2016 kl. 05:08 skrev John Bradley <ve7...@ve7jtb.com>:
On Feb 22, 2016, at 9:22 AM, Nat Sakimura <n-sakim...@nri.co.jp> wrote:
The risk impact of [case2] is more OAuth specific. The token is stolen as the
token is going to be sent to a rogue resource, and the resource can use that to
obtain the resource that was supposed to be only available to the proper client.
The risk impact of [case3] is the most grave among these three. Now the
attacker can create his own client that impersonates the compromised client.
OAuth-mix-up
---------------------------
OAuth-mix-up draft gives one way of addressing [case2] by introducing a new
concept of “issuer” and “discovery” to RFC6749. It also returns client_id and
verifies it in 4.2, but if the BadAS has assigned a same client_id to the
client, it does not help.
Client_id are not guaranteed to be unique. They need to be name spaced by the
AS. In OAuth currently we have no name for the AS this makes that difficult,
the client can use the authorization endpoint URI, but that logic may well
break in multi tenant situations. Having a clear issuer string makes it
easier for the client.
I stumbled over exactly this point when I made my implementation follow the
Mix-Up draft.
If not discovery is involved I think an AS has to have a name which is
different from the endpoint URIs.
One of the issue with this approach is that the central notion of “issuer” is
new to the existing servers and clients. The verification rule in 4.1 states
“Compare the issuer URL for the authorization server that the client received
when it registered at the authorization server”, but in most existing pure
OAuth cases, there is no such thing, so you cannot compare. This means that you
would have to re-register, and if you are doing that, the per-AS redirect_uri
seems to be a much simpler solution.
The client developers I have talked to really hate per AS redirect URI as being
too awkward for deployments.
I on the other hand found it quite easy to do per AS redirect URIs, so it might
well be implementation
dependent rather then contextual.
Per AS Redirect URI
--------------------------------
This does not involve wire protocol changes. It just adds requirements on the
redirect uri. This by far is the simplest solution for [case2] (and [case1]),
IMHO.
Again, it is not a general framework for finding out tainted communication, so
it may have other holes.
This is probably the hardest for the client developer and for the deployer.
Yes it is simplest from a spec point of view.
We need more developer feedback on this.
As I said above I found this quite simple to implement.
(Extended) PKCE
---------------------------------
To begin with, it works only with code flow. There has to be something else to
deal with implicit flow.
PKCE binds the authorization request/response to the token request.
If used with a confidential client, it seems to mitigate the vulnerability.
John points out that it is not the case. I must be missing something here… but
my logic goes like:
1. The good client creates code_challenge-v and
code_verifier-v=S256(code_challenge-v) and sends the client_id-v +
code_challenge-v + state to the BadAS Authz EP.
2. BadAS as a client prepares a code_verifier-b and
code_challenge-b=S256(code_verifer-b).
3. BadAS redirects to GoodAS with the client_id-v + code_challenge-b +
state-v.
4. GoodAS stores the code_challenge-b.
5. GoodAS returns code-v + state-v to the client’s redirect uri.
6. The client finds the AS from the state and sends code-v +
code_verifier-v + secret-b to the BadAS token endpoint. Now, code-v and
code_verifer-v is phished.
Now the attacker tries to use the code-v and code_verifier-v.
### Case A:
7. The BadAS as a client sends client_id-v + … but he does not have client
secret for the good client, so it fails.
### Case B:
8. The BadAS as a client sends client_id-b + code-v + code_verifier-b +
secret-b etc. to GoodAS.
9. GoodAS verifies the code_verifier-b is associated with code-v, but that
code-v is not associated with client_id-b, so the token request fails.
### Case C: cut-n-paste
10. The attacker launches cut-n-paste attack by replacing the code-b with
code-v.
11. The verifiers does not match, so fails.
Please let me know what I am missing.
In a step 0 the attacker has the good client create another request in the
attackers user agent to get state-0 and code_challange-0
Step 2 is not required.
Step 3 Bad AS redirects to good AS with client_id_v + state-v + code_challenge-0
Step 4 GoodAS stores code_challenge-0
Step 5 GoodAS returns code-v + state-v to the clients redirect_uri
Step 6 The client finds the AS from the state and sends code-v +
code_verifier-v + secret-b to the BadAS token endpoint. Now, code-v and
code_verifer-v is phished.
Case C1 : cut and paste
10. The attacker launches cut-n-paste attack by inserting code-v into a
response using state-0
11. The client sends code-v and based on state-0 it sends code_verifyer-0 to
the good AS token endpoint.
12. The GoodAS verifies that code-verifyer-0 is correct for code_challange-0
that it bound to code in step 4
13. The GoodAS receives RT + AT.
14. The attacker has now used the client to bind the users resource to it’s
account and is transferring money or looking at your data.
This could be 3rd party financial app like Mint as an example or photos or any
other PII that could then be used to escalate identity theft.
This variation of the attack combining cut and paste with confused client was
not mentioned in the research papers.
I found it looking to see if PKCE could be used to mitigate the confused client
attack.
As I mentioned in a response to William, while the current PKCE Challenge
methods only make the attack harder by forcing the attacker to get the client
to make a step 0 request to get a code_challenge to use in the request, we
could define a new challenge method that would be effective.
That would remove the need to have a separate mechanism to prevent cut and
paste.
The problem is that the PKCE challenge is independent of state so becomes
vulnerable to the confused client.
What we would need to do is include state in the challenge so that if the AS
receives mismatched state and code_challange in step 3 the verification of code
verifier will fail. Effectively combining the cut and paste mitigation with
PKCE.
I haven’t had time to write this up, but if the code_challenge == SHA256
(SHA256(state) || token_endpoint URI || Authorization_endpoint URI || client_id
|| code-veriyer) , then the attacker could not change state, client_id, or
token_endpoint independently of code_challenge. (note I am using a hash of
state to make storage size deterministic for the AS on the grounds that the
client already needs to be able to do the hash) (Some attacks change the
client_id in the request so I am including it in the hash)
This is slightly more complicated than than S256, but not that much. I wish I
had thought of this when we were doing PKCE. Hit me with the stupid stick, my
fault.
I don’t know if it stops all the confused client attacks though.
If the client is confidential then it gives up it’s client secret assuming
compromised registration, so we can’t really count on that for symmetric client
authentication.
By including the token endpoint in the comparison if the client is sending the
code to the attacker the client will use a different token endpoint_uri in to
calculate the code_challenge than the GoodAS will use to verify it. This
would stop both cut and paste as well as stopping the attacker from using the
code if they get it. The attacker can’t get Secret for state-0, so it can’t
create code_challenge that would be valid.
This stops the registration attack where the client gets a bad AS discovery
endpoint that has all the Good AS info including dynamic registration endpoint
but the bad AS token endpoint. The bad AS would get the token, client_secret
and code_verier, but will fail pkce verification because the token endpoint
will be wrong.
The attack where the client registers with the good AS but with bad token
endpoint and Authorization endpoint gives the attacker the ability to change
the code_challenge that the Good AS is going to see. It would need to make a
new challenge using state and the GoodAS token endpoint and it’s client_id.
To do that it needs the code_verifier to use to calculate the hash to use as
the code_challenge value. As long as the client is not tricked into accepting
a replay of the authentication response we should be safe. The client would
need to do replay protection on the code_verifier values before it makes a
request to the token endpoint.
The BadAS could however make up a new code_challenge and code_verifier and use
that in the request. For this one the AS would need to do pull discovery on the
client to get a key, or the AS needs to return something in the response. This
attack can completely proxy all the endpoints as far as the client is concerned
and is taking advantage of the AS saying you are granting permission to site X
based on the redirect URI.
I can’t see PKCE on it’s own being able to stop a client from being used as a
redirector back to the attacker unless you also returned the code_challenge in
the response from the authorization endpoint.
Hypothetically if we returned code_challenge in the response from the
authorization endpoint and have a new PKCE challenge method we might find it
covers all of the attacks.
We would need to put some serious analysis into this to see if it really covers
all the attacks.
It however doesn’t address the “token” response_type or steeling the access
token by impersonating the RS.
I think the correct way to stop the problem with access tokens is by audience
restricting them.
To do that the client needs to provide an audience in it’s request and the AS
needs to include that in the AT.
I included the Authorization_endpoint URI in the hash to detect if the auth
request may have been tampered with to change the audience for the AT.
For implicit we could have a version of PKCE where the AS returns a parameter
with S256( client_id || authorization_endpoint URI || resource endpoint URI) to
verify the request was not tampered with, and that would allow the AT to be
properly audience restricted.
This would be a completely new approach not involving discovery, logical names
for AS, or link relations.
Effectively this code_challenge method becomes a signature over parts of the
request and the implicit audience of the token_endpoint URI.
People keep asking why PKCE doesn’t stop these attacks, and it won’t with the
current PKCE methods, however a new method along the lines I sketched out may
let it work, or I could be completely wrong.
Once you have written down something more definite I promise to implement it
promptly such that we can do interop
testing early in the process.
Before John brought up this new PKCE mode I was on the Option A side of the
fence now I’d like to see more
of this PKCE idea before committing to one or the other.
— Roland
”Everybody should be quiet near a little stream and listen."
From ’Open House for Butterflies’ by Ruth Krauss
_______________________________________________
OAuth mailing list
OAuth@ietf.org
https://www.ietf.org/mailman/listinfo/oauth
--
Chief Architect
Identity Services Engineering Work: george.fletc...@teamaol.com
AOL Inc. AIM: gffletch
Mobile: +1-703-462-3494 Twitter: http://twitter.com/gffletch
Office: +1-703-265-2544 Photos: http://georgefletcher.photography
_______________________________________________
OAuth mailing list
OAuth@ietf.org
https://www.ietf.org/mailman/listinfo/oauth