[OAUTH-WG] Downgrade attacks on PKCE

Daniel Fett <fett@danielfett.de> Sat, 30 May 2020 07:58 UTC

Return-Path: <fett@danielfett.de>
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 7BA3F3A07E6 for <oauth@ietfa.amsl.com>; Sat, 30 May 2020 00:58:55 -0700 (PDT)
X-Virus-Scanned: amavisd-new at amsl.com
X-Spam-Flag: NO
X-Spam-Score: -2.096
X-Spam-Level:
X-Spam-Status: No, score=-2.096 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, HTML_MESSAGE=0.001, SPF_NONE=0.001, UNPARSEABLE_RELAY=0.001, URIBL_BLOCKED=0.001] autolearn=ham autolearn_force=no
Authentication-Results: ietfa.amsl.com (amavisd-new); dkim=pass (1024-bit key) header.d=danielfett.de
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 ONJE2u-6j4AO for <oauth@ietfa.amsl.com>; Sat, 30 May 2020 00:58:53 -0700 (PDT)
Received: from d3f.me (redstone.d3f.me [5.9.29.41]) (using TLSv1.2 with cipher ADH-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ietfa.amsl.com (Postfix) with ESMTPS id 44E1E3A07E1 for <oauth@ietf.org>; Sat, 30 May 2020 00:58:53 -0700 (PDT)
Received: from authenticated-user (PRIMARY_HOSTNAME [PUBLIC_IP]) by d3f.me (Postfix) with ESMTPA id 6AFEE6483 for <oauth@ietf.org>; Sat, 30 May 2020 07:58:50 +0000 (UTC)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=danielfett.de; s=dkim; t=1590825530; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type; bh=+jL8hUBoszwTZ4ggxxrSAca6EypwY8ToOTvUW1FXPNQ=; b=pF2Hr7ITGvpcDRDQgC9SwArcCRjb0ofAWnWXiSe6TTQLDkZtBBOLwNzLfifFeGd/EMlYsd +huUiVtVX3kII9jNWgDilil9/OEY7TCXCqigF0l2JSIq1sxdZ+IpB3aGu3LofIIzZ1Z9fy e69R72lC0o9QOSt6ZMe6EdlPse7eMRk=
To: "oauth@ietf.org" <oauth@ietf.org>
From: Daniel Fett <fett@danielfett.de>
Message-ID: <3e18622b-5135-be90-0ce9-23676be4fc50@danielfett.de>
Date: Sat, 30 May 2020 09:58:49 +0200
MIME-Version: 1.0
Content-Type: multipart/alternative; boundary="------------38C5B8B49D9B7BBB3DA3E51E"
Content-Language: de-DE
ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=danielfett.de; s=dkim; t=1590825530; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type; bh=+jL8hUBoszwTZ4ggxxrSAca6EypwY8ToOTvUW1FXPNQ=; b=e3A2UJM4cgRldx7gSoiylialsCyrORespkuRq2wjO7NAy9nwEmE2VaVHFpiI8kbf7QdIVF qYwL8tAMykC7gIUa3Tt0LV5zH735j+o9MwYlximXbYCw7bTfFW6kNyPrOCCvdQpUrySMaF a9EnboeSW+VhKtk7syb4ohTd8IfrqEA=
ARC-Seal: i=1; s=dkim; d=danielfett.de; t=1590825530; a=rsa-sha256; cv=none; b=Fp8VNJF/HUHSEZwFdoVi4/Ot0FvxwSMwJ0ZfTm+8vt7jG2qFer7SYdhbqxXl4hwG8qgZyv B+Z8u7Tmkjr5sg2exz6Wn5stZbGUIA4bkL7E1r5wTeMN31DpvOHdP7UClyQU4v5d0MKzpv SKhWD57hSOpaJ1t81yP3RDMtcPzBBc0=
ARC-Authentication-Results: i=1; d3f.me; auth=pass smtp.auth=fett@danielfett.de smtp.mailfrom=fett@danielfett.de
Authentication-Results: d3f.me; auth=pass smtp.auth=fett@danielfett.de smtp.mailfrom=fett@danielfett.de
X-Spamd-Bar: /
Archived-At: <https://mailarchive.ietf.org/arch/msg/oauth/0F3wPKS9w8SVL5WZH6AlZ0T16GU>
Subject: [OAUTH-WG] Downgrade attacks on PKCE
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: Sat, 30 May 2020 07:58:56 -0000

Hi all,

Aaron, Dick, Torsten and I today discussed the downgrade attacks on PKCE
[1] and how to mitigate them in OAuth 2.1 and 2.0. We came to the
conclusion that we have two options:

*1. "Static" Solution*

For every client_id that is registered with an AS, the AS MUST either
always enforce the use of PKCE or always enforce the use of nonce.
Whether PKCE or nonce is enforced can be part of the client registration
or configured in other ways.

In other words: A single client is not allowed to switch between using
PKCE and using nonce.

Note that the client is allowed to use the respective other mechanism on
top of the enforced one.

Properties:

  * Easy to understand mitigation.
  * Implementation is mainly a new data field and a check in the
    authorization request.
  * Not compatible to deployments where clients sometimes use nonce and
    sometimes use PKCE with the same client_id. *
    ***

**

*2. "Dynamic" Solution*

Each AS that supports PKCE MUST check whether a code challenge is
contained in the authorization request. This information MUST be bound
to the code that is issued.

When a code arrives at the token endpoint, the AS MUST do the following
check:

 1. If there was a code_challenge in the authorization request for which
    this code was issued, there must be a code_verifier in the token
    request and it must be verified according to RFC7636. (This is no
    change from the current behavior in RFC7636.)
 2. If there was no code_challenge in the authorization request, any
    request to the token endpoint containing a code_verifier MUST be
    rejected.

Properties:

  * No change in behavior needed for properly implemented clients.
    Backwards compatible for all existing deployments.
  * Implementation is mainly some logic for the authorization endpoint,
    token endpoint, and a new data field in the authorization session
    maintained by the AS.
  * Slightly more complex to implement for the AS, maybe.

We would like to hear the feedback from the working group on these two
solutions before proceeding to propose wording for the affected documents.

[1] https://danielfett.de/2020/05/16/pkce-vs-nonce-equivalent-or-not/

-Daniel