Re: [OAUTH-WG] Edge case in RFC 7636, Server Verifies code_verifier facilitates Login-CSRF

Thomas Broyer <t.broyer@gmail.com> Wed, 05 January 2022 18:01 UTC

Return-Path: <t.broyer@gmail.com>
X-Original-To: oauth@ietfa.amsl.com
Delivered-To: oauth@ietfa.amsl.com
Received: from localhost (localhost [127.0.0.1]) by ietfa.amsl.com (Postfix) with ESMTP id 09D563A0836 for <oauth@ietfa.amsl.com>; Wed, 5 Jan 2022 10:01:13 -0800 (PST)
X-Virus-Scanned: amavisd-new at amsl.com
X-Spam-Flag: NO
X-Spam-Score: -0.844
X-Spam-Level:
X-Spam-Status: No, score=-0.844 tagged_above=-999 required=5 tests=[BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, HTML_FONT_LOW_CONTRAST=0.001, HTML_MESSAGE=0.001, NUMERIC_HTTP_ADDR=1.242, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_KAM_HTML_FONT_INVALID=0.01, URIBL_BLOCKED=0.001] autolearn=unavailable autolearn_force=no
Authentication-Results: ietfa.amsl.com (amavisd-new); dkim=pass (2048-bit key) header.d=gmail.com
Received: from mail.ietf.org ([4.31.198.44]) by localhost (ietfa.amsl.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id bLLnF2VDn1kx for <oauth@ietfa.amsl.com>; Wed, 5 Jan 2022 10:01:07 -0800 (PST)
Received: from mail-yb1-xb2d.google.com (mail-yb1-xb2d.google.com [IPv6:2607:f8b0:4864:20::b2d]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by ietfa.amsl.com (Postfix) with ESMTPS id 440DD3A0834 for <oauth@ietf.org>; Wed, 5 Jan 2022 10:01:07 -0800 (PST)
Received: by mail-yb1-xb2d.google.com with SMTP id w184so189964ybg.5 for <oauth@ietf.org>; Wed, 05 Jan 2022 10:01:07 -0800 (PST)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=mime-version:references:in-reply-to:from:date:message-id:subject:to :cc; bh=6qcBUEztydCw2EdKdfTuW5V4vq5goRDLcn0R6GejjJI=; b=niScdkL6PHyy+AI12WPdAneqv021hkTHCa/xh6q0YUcBXv5A+4pyF2K+d5W8EnVp5g IcgH1Wr0LO0Fo4d7YmToAnw2LeNAujuDwAi5I4QSm8O4+UL19G0q/acdQWGbJL4qs+j5 H6pEIQqMSc2baEC/7k7zKr4Pxo1pIRf3FJB4YKkI4pdtLH6xND1nauXS3IodfKvPPRmj zPqgzGwH+mfGL0Embd+aMxwRk0+jLKUu5WaqpZpXtWK+Q6uzMFPxgzPPmYqB7b58l0bC uvrRXwFe/+K0iFhSrGIpTqxdR1yqQNlhTb84/xH1m8FAiacdJpWlkvG6df1e9FCDC1dx yQUw==
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc; bh=6qcBUEztydCw2EdKdfTuW5V4vq5goRDLcn0R6GejjJI=; b=0LAXmMFWIKPTKXo2EH8eQEWNmdoEHET1cVzNSo8RAfoyAFM4EVu+IGoyvinPWrAudN nOXIUiJcJv/++69qrdOu5Q3ljlRAfEsixTUro3vCBHsu+cAolbSXlb8N5qg6a2cmVAYT 1bbrb4WGM2sEudYGbW5cTjS+V+sG4p0FoymzSRKD6emdxlgfFQZ5MmA0HVMI8wCkDXML o6/30YgKju5W2DgN1dwx66WiTRcOx3twRrhZUorQoOJvUxoo3qrwcg6ymcSrTsXku9KO p2QPzMp/hW320DU0vhYhyIzNjuflC91mcvXeM2nT8aeN1I5YGaTQHBeklARzxK8BQ94M F3sg==
X-Gm-Message-State: AOAM530PJ7q77vluVefjCNKkQOXi78tFW2gf+W8bGEe6A5QlkH8TolvU I+Y/DQu7bDx6+4FTCA9dfoTViu2FLSyVV1HUOXI=
X-Google-Smtp-Source: ABdhPJy6N8xicGudDBRgJRZgy5soLIw4KZnHSQe6B3JOMLu+o4op0C2vJ0qWgJ2+BXEyUmjV5vWpWwzBKA2cTx+NLyA=
X-Received: by 2002:a25:b9cf:: with SMTP id y15mr69276493ybj.540.1641405665316; Wed, 05 Jan 2022 10:01:05 -0800 (PST)
MIME-Version: 1.0
References: <AM7P192MB0819568B6CF315C3BC3A9B15E44A9@AM7P192MB0819.EURP192.PROD.OUTLOOK.COM> <b711bc01-9674-6072-d941-7e1ba8f8c9ec@aol.com> <AM7P192MB081909F590F651D656ACC892E44B9@AM7P192MB0819.EURP192.PROD.OUTLOOK.COM> <CAJot-L2o32DCswBAoq6DKZgZmEKgafEk=_AGnj5y3q3CBPsa3A@mail.gmail.com> <AM7P192MB0819D3D6523981A8495D5CD7E44B9@AM7P192MB0819.EURP192.PROD.OUTLOOK.COM> <6Kxw1IhJ0CB5svSOaCq1pBJLwZcQNvswr1Uw4mq8xswG9Z8fDMMevvE95zYV8WxcT1eLriglIcDv1hPr3j-d5GQ0ByLae9zC2HM8SVmoHUI=@protonmail.ch> <CAJot-L2r7u2iL6cGEQPZg0N4SkiXTinmMLrXQZT0YN20U39vYw@mail.gmail.com> <db3efddd-ac34-116e-f5c1-64b916c4771e@aol.com>
In-Reply-To: <db3efddd-ac34-116e-f5c1-64b916c4771e@aol.com>
From: Thomas Broyer <t.broyer@gmail.com>
Date: Wed, 05 Jan 2022 19:00:54 +0100
Message-ID: <CAEayHEPw=_Y9QybDOKrFvh9MaHhvvGOATGRc=uYVNzN9z1Phzw@mail.gmail.com>
To: George Fletcher <gffletch=40aol.com@dmarc.ietf.org>
Cc: Warren Parad <wparad=40rhosys.ch@dmarc.ietf.org>, Christopher Burroughs <chris.burroughs@protonmail.ch>, oauth <oauth@ietf.org>
Content-Type: multipart/alternative; boundary="0000000000009d175e05d4d989b4"
Archived-At: <https://mailarchive.ietf.org/arch/msg/oauth/1GrLLdhLqPakCXt8AsCKbpLW5h4>
Subject: Re: [OAUTH-WG] Edge case in RFC 7636, Server Verifies code_verifier facilitates Login-CSRF
X-BeenThere: oauth@ietf.org
X-Mailman-Version: 2.1.29
Precedence: list
List-Id: OAUTH WG <oauth.ietf.org>
List-Unsubscribe: <https://www.ietf.org/mailman/options/oauth>, <mailto:oauth-request@ietf.org?subject=unsubscribe>
List-Archive: <https://mailarchive.ietf.org/arch/browse/oauth/>
List-Post: <mailto:oauth@ietf.org>
List-Help: <mailto:oauth-request@ietf.org?subject=help>
List-Subscribe: <https://www.ietf.org/mailman/listinfo/oauth>, <mailto:oauth-request@ietf.org?subject=subscribe>
X-List-Received-Date: Wed, 05 Jan 2022 18:01:13 -0000

On Wed, Jan 5, 2022 at 5:51 PM George Fletcher <gffletch=
40aol.com@dmarc.ietf.org> wrote:

> 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)
>

Not necessarily for that second point, but it must accept authorization
response messages without state.
The user can be triggered to initiate the authorization process (resulting
in the client storing some state in a cookie/session), so that when the
authorization response message comes in with the attacker-supplied
authorization_code, the client accepts it (cookie/session is present, so
it's not deemed "uninitiated")
Mitigation is to use state in addition to PKCE.

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.burroughs@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.Haeublein@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
>>
>> 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 <wparad@rhosys.ch>
>> *Gesendet:* Mittwoch, 5. Januar 2022 13:44
>> *An:* Benjamin Häublein <Benjamin.Haeublein@cirosec.de>
>> *Cc:* George Fletcher <gffletch@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 "wparad@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.Haeublein@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 <gffletch@aol.com>
>> *Gesendet:* Dienstag, 4. Januar 2022 14:51
>> *An:* Benjamin Häublein <Benjamin.Haeublein@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
>>
>> 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
>>
>> 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 listOAuth@ietf.orghttps://www.ietf.org/mailman/listinfo/oauth
>
>
> _______________________________________________
> OAuth mailing list
> OAuth@ietf.org
> https://www.ietf.org/mailman/listinfo/oauth
>


-- 
Thomas Broyer
/tɔ.ma.bʁwa.je/ <http://xn--nna.ma.xn--bwa-xxb.je/>