Re: [OAUTH-WG] Edge case in RFC 7636, Server Verifies code_verifier facilitates Login-CSRF
Christopher Burroughs <chris.burroughs@protonmail.ch> Wed, 05 January 2022 14:56 UTC
Return-Path: <chris.burroughs@protonmail.ch>
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 316EF3A0B35 for <oauth@ietfa.amsl.com>; Wed, 5 Jan 2022 06:56:50 -0800 (PST)
X-Virus-Scanned: amavisd-new at amsl.com
X-Spam-Flag: NO
X-Spam-Score: -0.753
X-Spam-Level:
X-Spam-Status: No, score=-0.753 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, RCVD_IN_MSPIKE_H3=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_PASS=-0.001, URIBL_BLOCKED=0.001, URI_HEX=0.1] autolearn=ham autolearn_force=no
Authentication-Results: ietfa.amsl.com (amavisd-new); dkim=pass (2048-bit key) header.d=protonmail.ch
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 kdes0yW6CF4p for <oauth@ietfa.amsl.com>; Wed, 5 Jan 2022 06:56:45 -0800 (PST)
Received: from mail-40133.protonmail.ch (mail-40133.protonmail.ch [185.70.40.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ietfa.amsl.com (Postfix) with ESMTPS id B086C3A0B31 for <oauth@ietf.org>; Wed, 5 Jan 2022 06:56:44 -0800 (PST)
Date: Wed, 05 Jan 2022 14:56:01 +0000
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=protonmail.ch; s=protonmail2; t=1641394599; bh=nGInPhhIVoLONWDUR04noWrqxy14F5WS9b2pFY5y0lY=; h=Date:To:From:Cc:Reply-To:Subject:Message-ID:In-Reply-To: References:From:To:Cc; b=RQa31tC56g4uyNf6hbr0Gnmx5yMXLWgBOkXc38c6Fl5Tpedz4RlpyEAswgIGvtIro gvDHRv55PTtfx7Op3HZwKcBZwBdft9F0DxFAsLxcG+BX+y/vXIdc6mgzyemDkFr8jc iIT5oDhWl+j+W2gy1TnrDpY3ZG5MYrZhLYYTVQLyfHVogO84RXHQjX4O4xwHD1zoz2 twSzSBO6aU5i6Goiv9F2GDMe5glpCFVZxXtRSLOa0F1/w2wFCEQCwz8rBDR5QyvwCo FZfSUjNeAdYmoDTc0L6inDZX7frd9PzsHuFc1hlXYB671sPD2GIOebPreEPevfReCC 1TRiCUYi4DqKQ==
To: Benjamin.Haeublein@cirosec.de, wparad@rhosys.ch
From: Christopher Burroughs <chris.burroughs@protonmail.ch>
Cc: oauth@ietf.org
Reply-To: Christopher Burroughs <chris.burroughs@protonmail.ch>
Message-ID: <6Kxw1IhJ0CB5svSOaCq1pBJLwZcQNvswr1Uw4mq8xswG9Z8fDMMevvE95zYV8WxcT1eLriglIcDv1hPr3j-d5GQ0ByLae9zC2HM8SVmoHUI=@protonmail.ch>
In-Reply-To: <AM7P192MB0819D3D6523981A8495D5CD7E44B9@AM7P192MB0819.EURP192.PROD.OUTLOOK.COM>
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>
MIME-Version: 1.0
Content-Type: multipart/alternative; boundary="b1_pnKdi5n13whRas1v1zqTk8mBY3wOlHCjEbUp23yQo"
Archived-At: <https://mailarchive.ietf.org/arch/msg/oauth/OXd8W-JqysY5nrqZkiKv5KWUoUs>
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 14:56:50 -0000
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 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-74www.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:] >>> >>> - Enforce usage of PKCE in the client configuration in the Authorization Server >>> >>> - 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. >>> >>> - 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-WG] Edge case in RFC 7636, Server Verifies… Benjamin Häublein
- Re: [OAUTH-WG] Edge case in RFC 7636, Server Veri… George Fletcher
- Re: [OAUTH-WG] Edge case in RFC 7636, Server Veri… Daniel Fett
- Re: [OAUTH-WG] Edge case in RFC 7636, Server Veri… Benjamin Häublein
- Re: [OAUTH-WG] Edge case in RFC 7636, Server Veri… Warren Parad
- Re: [OAUTH-WG] Edge case in RFC 7636, Server Veri… Benjamin Häublein
- Re: [OAUTH-WG] Edge case in RFC 7636, Server Veri… Christopher Burroughs
- Re: [OAUTH-WG] Edge case in RFC 7636, Server Veri… Warren Parad
- Re: [OAUTH-WG] Edge case in RFC 7636, Server Veri… George Fletcher
- Re: [OAUTH-WG] Edge case in RFC 7636, Server Veri… Thomas Broyer