The following example shows this behavior in keycloak:
Authorization Request:
http://identity-provider:8080/auth/realms/XXX/protocol/openid-connect/auth?client_id=client-spa-public-pkce&redirect_uri=http%3A%2F%2Flocalhost%2F&response_mode=fragment&response_type=code&scope=openid
Authorization Response:
http://127.0.0.1/#session_state=46556363-c53f-489f-871c-58d376a8f9c1&code=2b84ee14-68ff-48c9-b480-4349ff9805f7.46556363-c53f-489f-871c-58d376a8f9c1.6fab0727-6184-47ad-8607-55f19896e945
Token Request:
POST /auth/realms/XXX/protocol/openid-connect/token HTTP/1.1
Host: identity-provider:8080
Content-type: application/x-www-form-urlencoded

code=2b84ee14-68ff-48c9-b480-4349ff9805f7.46556363-c53f-489f-871c-58d376a8f9c1.6fab0727-6184-47ad-8607-55f19896e945&grant_type=authorization_code&client_id=client-spa-public-pkce&redirect_uri=http%3A%2F%2Flocalhost%2F&code_verifier=IqiCQGM06JEyW73AB3f3oblCQKHOorapyqHUcYRujuSikDJx8cvBQ0kmFmzW75uIfaSBtXQrRmwuk71WWO6ryCzahTcxBPYX

As a result, an access token was issued although the code_verifier provided in 
the token request did not match the code_challenge and code_challenge_method in 
the authorization request as they were absent.

An attacker can thus send the victim the authorization response, after the 
victim clicks the link, the client application sends a Token Request with the 
code_verifier present with the client to Keycloak.
As a result, a token is issued for the application, although the code_verifier 
does not match the inexistent code_challenge/code_challenge_method in the 
malicious authorization response.

For this to work, the client must either generate a code_verifier on the fly or 
have one already present. This obviously depends on the precise implementation 
of the respective client.
To reach such a state, an attacker could trick the user into starting the 
authorization grant but clicking the malicious link before the authorization 
response is sent.

Best Regards,
Benjamin Häublein
Senior Consultant

cirosec GmbH
Ferdinand-Braun-Strasse 4
74074 Heilbronn
Germany
Phone: +49 (7131) 59455-74
Fax: +49 (7131) 59455-99
Mobile: +49 (151) 122414-74
www.cirosec.de

HRB Stuttgart 107883
CEO Stefan Strobel, CFO Peter Lips

Von: Warren Parad <wpa...@rhosys.ch>
Gesendet: Mittwoch, 5. Januar 2022 13:44
An: Benjamin Häublein <benjamin.haeubl...@cirosec.de>
Cc: George Fletcher <gffle...@aol.com>; oauth@ietf.org
Betreff: Re: [OAUTH-WG] Edge case in RFC 7636, Server Verifies code_verifier 
facilitates Login-CSRF

Sie erhalten nicht oft E-Mail von "wpa...@rhosys.ch<mailto:wpa...@rhosys.ch>". 
Weitere Informationen, warum dies wichtig 
ist<http://aka.ms/LearnAboutSenderIdentification>
I'm not following to be honest. Could you detail concretely what the flow would 
be that would result in vulnerability?


[https://lh6.googleusercontent.com/DNiDx1QGIrSqMPKDN1oKevxYuyVRXsqhXdfZOsW56Rf2A74mUKbAPtrJSNw4qynkSjoltWkPYdBhaZJg1BO45YOc1xs6r9KJ1fYsNHogY-nh6hjuIm9GCeBRRzrSc8kWcUSNtuA]

Warren Parad

Founder, CTO
Secure your user data with IAM authorization as a service. Implement 
Authress<https://authress.io/>.


On Wed, Jan 5, 2022 at 1:41 PM Benjamin Häublein 
<benjamin.haeubl...@cirosec.de<mailto:benjamin.haeubl...@cirosec.de>> wrote:
Finally, I'm not sure a client that doesn't send the 'code_challenge' and 
'code_challenge_method' on the authorization request but does send the 
'code_verifier' on the token request should consider that the client has 
implemented PKCE correctly and hence can rely on it for CSRF.
My point is not, that a client behaves that way. The problem is that an 
attacker could get a user (through social engineering) to start the 
authorization process and then click a link with an authorization response that 
the attacker provides.
Then the client has send the 'code_challenge' and 'code_challenge_method' in 
the authorization request, but the authorization response belongs to an 
authorization request that does not have these parameters.
When the client sends the token request based on the malicious authorization 
request but with the ‘code_verifier’ for the original authorization request.
When the AS behaves as described the client has no way to know that an attacker 
has interfered.

Best Regards,
Benjamin Häublein
Von: George Fletcher <gffle...@aol.com<mailto:gffle...@aol.com>>
Gesendet: Dienstag, 4. Januar 2022 14:51
An: Benjamin Häublein 
<benjamin.haeubl...@cirosec.de<mailto:benjamin.haeubl...@cirosec.de>>; 
oauth@ietf.org<mailto:oauth@ietf.org>
Betreff: Re: [OAUTH-WG] Edge case in RFC 7636, Server Verifies code_verifier 
facilitates Login-CSRF

My guess is that for an Authorization Server that doesn't receive a 
'code_challenge' and 'code_challenge_method' as part of the authorization 
request, they treat the request as a non-PKCE authorization request. Therefore 
when the 'code_verifier' is presented at the /token endpoint, the AS ignores 
the parameter because it doesn't consider the request to be a PKCE request. I 
can also see the AS returning an error regarding an "unexpected parameter" or 
"invalid request" error in this case.

I agree with your recommendation for the AS to require specific clients to use 
PKCE and consider an authorization request without PKCE to be an error.

Finally, I'm not sure a client that doesn't send the 'code_challenge' and 
'code_challenge_method' on the authorization request but does send the 
'code_verifier' on the token request should consider that the client has 
implemented PKCE correctly and hence can rely on it for CSRF.

Thanks,
George
On 1/4/22 5:45 AM, Benjamin Häublein wrote:
Hello everyone,
I think RFC 7636 “Proof Key for Code Exchange by OAuth Public Clients”, section 
4.6. “Server Verifies code_verifier before Returning the Tokens” leaves a tiny 
gap regarding the handling of verification when no code challenge was present 
in the authorization request:
   Upon receipt of the request at the token endpoint, the server
   verifies it by calculating the code challenge from the received
   "code_verifier" and comparing it with the previously associated
   "code_challenge", after first transforming it according to the
   "code_challenge_method" method specified by the client.
It is unspecified how the server should behave when “code_verifier” is present, 
but “code_challenge” and “code_challenge_method” were not set in the initial 
authorization request.
The following example worked for three well-known authorization servers where 
the client was configured in a way that PKCE could be used, but was not 
enforced:
Authorization Request:
https://XXXX/auth?client_id=YYYY&response_type=code&scope=openid+profile&redirect_uri=https://localhost
Subsequent Token Request:
POST /token HTTP/1.1
Host: XXXX
Content-Length: 256

code=ZZZZ&grant_type=authorization_code&client_id=YYYY&redirect_uri=https%3A%2F%2Flocalhost&code_verifier=IqiCQGM06JEyW73AB3f3oblCQKHOorapyqHUcYRujuSikDJx8cvBQ0kmFmzW75uIfaSBtXQrRmwuk71WWO6ryCzahTcxBPYX
As a result, an access token was issued although the code_verifier provided in 
the token request did not match the code_challenge and code_challenge_method in 
the authorization request.

Many applications consider the usage of PKCE as enough protection from 
Login-CSRF and do not use state or nonce (for example this blog entry by Daniel 
Fett https://danielfett.de/2020/05/16/pkce-vs-nonce-equivalent-or-not/ 
suggests, that neither state nor nonce are necessary when PKCE is used). 
However, when the authorization server is not configured to require a specific 
code_challenge_method from the client and the authorization behaves as 
described in the example, PKCE does not protect from Login-CSRF.
I think the following mitigations are possible:

  1.  Enforce usage of PKCE in the client configuration in the Authorization 
Server
  2.  Implementation of the authorization server returns an error in the Access 
Token Response when code_verifier is present in the token request, but no 
code_challenge and code_challenge_method is present in the authorization 
request.
  3.  Additionally, when the behavior of an AS is correct (verification of 
code_verifier fails when no code_challenge was present), a client that relies 
on PKCE for CSRF protection must always include a code_verifier parameter in 
the token request (even if no code_verifier is present on the client side).

Best regards,

Benjamin Häublein
Senior Consultant

cirosec GmbH
Ferdinand-Braun-Strasse 4
74074 Heilbronn
Germany
Phone: +49 (7131) 59455-74
Fax: +49 (7131) 59455-99
Mobile: +49 (151) 122414-74
www.cirosec.de<http://www.cirosec.de>

HRB Stuttgart 107883
CEO Stefan Strobel, CFO Peter Lips



_______________________________________________

OAuth mailing list

OAuth@ietf.org<mailto:OAuth@ietf.org>

https://www.ietf.org/mailman/listinfo/oauth

_______________________________________________
OAuth mailing list
OAuth@ietf.org<mailto:OAuth@ietf.org>
https://www.ietf.org/mailman/listinfo/oauth

Attachment: smime.p7s
Description: S/MIME cryptographic signature

_______________________________________________
OAuth mailing list
OAuth@ietf.org
https://www.ietf.org/mailman/listinfo/oauth

Reply via email to