So it seems to me, two factors need to be present for something "bad" to happen...

1. The client always sends PKCE but the AS doesn't require the client to use PKCE 2. The client must accept uninitiated authorization response messages (i.e. from the attacker)

If either of the above are not true, then I think any attack fails. Please correct me if I'm wrong.

Mitigations then are...
1. AS requires designated clients to always provide PKCE parameters and fails the /authorization request if they are not present
2. The client does not accept uninitiated authorization response messages

It's best if both mitigations are implemented along with others identified in this thread.

My 2 cents:)

Thanks,
George

On 1/5/22 10:24 AM, Warren Parad wrote:
The PKCE downgrade attack is the converse, here we are adding in PKCE where there was none.

    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.

That isn't the whole flow though, right? You are missing what the authorization request the attacker sent to the AS is, as well what happens after the user agent gets back the access token, how is a token generated this way a vulnerability.

I think I see the suggested problem:

if an AS-client interaction supports both PKCE and not PKCE, and the client assumes that PKCE is sufficient for CSRF, when the auth code request doesn't include the PKCE but the client didn't send state/nonce. With OAuth 2.1 it is clear that the nonce/state must be sent in this situation:

  * State is required in OAuth authorization code requests if PKCE
    isn't specified: OAuth 2.1 section 7.7
    <https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-04#section-7.7>
  * State is required in OAuth token exchange requests if present:
    Section 4.1.2
    
<https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-04#section-4.1.2>

Since the user agent won't contain the valid state/nonce generated by the attacker, it isn't possible for it to send the attacker's state to the AS. Therefore the AS will reject the token exchange due to the state mismatch. It doesn't matter if the request isn't protected against CSRF, because no valid token is going to be returned anyway.

So I don't think there is an issue here, did I get that correct?

        

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 3:56 PM Christopher Burroughs <chris.burrou...@protonmail.ch> wrote:

    Greetings,


    Is this scenario any different from a PKCE downgrade attack, as
    described in OAuth 2.0 Security Best Current Practice section 4.8.2 ?


    Warm regards and happy new year!


    Christopher Burroughs





    -------- Original Message --------
    On Jan 5, 2022, 21:29, Benjamin Häublein <
    benjamin.haeubl...@cirosec.de> wrote:


        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
        
<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
        
<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 <http://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". 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?


                

        *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> 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>
            *Gesendet:* Dienstag, 4. Januar 2022 14:51
            *An:* Benjamin Häublein <benjamin.haeubl...@cirosec.de>;
            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
                
<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

                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
_______________________________________________
OAuth mailing list
OAuth@ietf.org
https://www.ietf.org/mailman/listinfo/oauth

Reply via email to