From nobody Wed Jan  5 00:57:14 2022
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 722563A09D1
 for <oauth@ietfa.amsl.com>; Wed,  5 Jan 2022 00:57:12 -0800 (PST)
X-Virus-Scanned: amavisd-new at amsl.com
X-Spam-Flag: NO
X-Spam-Score: -2.098
X-Spam-Level: 
X-Spam-Status: No, score=-2.098 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_PASS=-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 7c2q2W3PjI_b for <oauth@ietfa.amsl.com>;
 Wed,  5 Jan 2022 00:57:08 -0800 (PST)
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 3A5ED3A09D0
 for <oauth@ietf.org>; Wed,  5 Jan 2022 00:57:07 -0800 (PST)
Received: from authenticated-user (PRIMARY_HOSTNAME [PUBLIC_IP])
 by d3f.me (Postfix) with ESMTPA id 3AC6FCA1A
 for <oauth@ietf.org>; Wed,  5 Jan 2022 08:57:03 +0000 (UTC)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=danielfett.de;
 s=dkim; t=1641373023;
 h=from:from:reply-to:subject:subject:date:date:message-id:message-id:
 to:to:cc:mime-version:mime-version:content-type:content-type:
 in-reply-to:in-reply-to:references:references;
 bh=HgK+e69o5LiBX/FbpSh0IiM5Otoat/f7TAm+BUpDYSs=;
 b=HEcAVOsWIq8ag6E827nQ/od+MVxpcplV3HJznU0bHGI6kE+NUr42YuA9PDB35c++Mn0yt3
 Jw/kCXaS8QgNmNt4UCt0CPYKPVViJftQsvXQDLDySGI6HGVrPgO9t6u8Ne0mbUL6JR6lgW
 oqj6rzSGAeLyMjgXLDzuBQwrOOWUpHI=
To: oauth@ietf.org
References: <AM7P192MB0819568B6CF315C3BC3A9B15E44A9@AM7P192MB0819.EURP192.PROD.OUTLOOK.COM>
From: Daniel Fett <fett@danielfett.de>
Message-ID: <6d130253-5b55-baae-4718-170e4b6bdb5c@danielfett.de>
Date: Wed, 5 Jan 2022 09:57:02 +0100
MIME-Version: 1.0
In-Reply-To: <AM7P192MB0819568B6CF315C3BC3A9B15E44A9@AM7P192MB0819.EURP192.PROD.OUTLOOK.COM>
Content-Type: multipart/alternative;
 boundary="------------B31A28B35D92BE8613BA2A1C"
Content-Language: de-DE
ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=danielfett.de; 
 s=dkim; t=1641373023;
 h=from:from:reply-to:subject:subject:date:date:message-id:message-id:
 to:to:cc:mime-version:mime-version:content-type:content-type:
 in-reply-to:in-reply-to:references:references;
 bh=HgK+e69o5LiBX/FbpSh0IiM5Otoat/f7TAm+BUpDYSs=;
 b=dSgEONZ8mhlT3PlaCfaAlgWsprF24xxBlVe1hdz5KstcdX4oVNENUqPluc0ceW+TLZV6K/
 Q7HX7nLDzsNwVNxReJ+6d7nC5b+XvJ8bmTIAZTVlyCAxaFCaQkAo8MhiNcdHXBi24kHfrM
 XZpwRjMGl6lJpV0TsGCNLr28Fk0iPLw=
ARC-Seal: i=1; s=dkim; d=danielfett.de; t=1641373023; a=rsa-sha256; cv=none;
 b=b00uEMAE/RknMW+Ce7d4uzcq1F+ZasUGJJN8hB6Woai2CyHQgdH3d5xnGGVGLc6exX2WiM
 IFJVU6oJ07FSGWDgXUacwAILnsKzDYIqMdelyk9s9GrHKDnN/SDat7Nh7cVXcqBycBooDH
 3cB3mmgZViZimrnfDCK6BTmMTdb2wJU=
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/j9Syg-Vd4XiK9_njQGQ_DA2XqLY>
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 08:57:13 -0000

This is a multi-part message in MIME format.
--------------B31A28B35D92BE8613BA2A1C
Content-Type: text/plain; charset=windows-1252
Content-Transfer-Encoding: 8bit

Hi Benjamin,

thanks for bringing this up!

What you describe is essentially a downgrade from PKCE to a non-PKCE flow.

Nov Matake pointed out this possibility in an earlier discussion:
https://mailarchive.ietf.org/arch/msg/oauth/qrLAf3nWRt8HAFkO49qGrPRuelo/

We therefore added this attack to the Security BCP:
https://datatracker.ietf.org/doc/html/draft-ietf-oauth-security-topics-19#page-28

As countermeasures, the BCP lists

   Beyond this, to prevent PKCE downgrade attacks, the AS MUST ensure
   that if there was no code_challenge in the authorization request, a
   request to the token endpoint containing a code_verifier is rejected.

   Note: AS that mandate the use of PKCE in general or for particular
   clients implicitly implement this security measure.

-Daniel



Am 04.01.22 um 11:45 schrieb Benjamin Häublein:
>
> 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/
> <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


-- 
https://danielfett.de


--------------B31A28B35D92BE8613BA2A1C
Content-Type: text/html; charset=windows-1252
Content-Transfer-Encoding: 8bit

<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html;
      charset=windows-1252">
  </head>
  <body>
    <div class="moz-cite-prefix">Hi Benjamin,</div>
    <p>thanks for bringing this up!</p>
    <p>What you describe is essentially a downgrade from PKCE to a
      non-PKCE flow. <br>
    </p>
    <p>Nov Matake pointed out this possibility in an earlier discussion:
      <br>
<a class="moz-txt-link-freetext" href="https://mailarchive.ietf.org/arch/msg/oauth/qrLAf3nWRt8HAFkO49qGrPRuelo/">https://mailarchive.ietf.org/arch/msg/oauth/qrLAf3nWRt8HAFkO49qGrPRuelo/</a></p>
    <p>We therefore added this attack to the Security BCP: <br>
<a class="moz-txt-link-freetext" href="https://datatracker.ietf.org/doc/html/draft-ietf-oauth-security-topics-19#page-28">https://datatracker.ietf.org/doc/html/draft-ietf-oauth-security-topics-19#page-28</a></p>
    <p>As countermeasures, the BCP lists</p>
    <p>   Beyond this, to prevent PKCE downgrade attacks, the AS MUST
      ensure<br>
         that if there was no code_challenge in the authorization
      request, a<br>
         request to the token endpoint containing a code_verifier is
      rejected.<br>
      <br>
         Note: AS that mandate the use of PKCE in general or for
      particular<br>
         clients implicitly implement this security measure.</p>
    <p>-Daniel<br>
    </p>
    <p><br>
    </p>
    <p><br>
    </p>
    <div class="moz-cite-prefix">Am 04.01.22 um 11:45 schrieb Benjamin
      Häublein:<br>
    </div>
    <blockquote type="cite"
cite="mid:AM7P192MB0819568B6CF315C3BC3A9B15E44A9@AM7P192MB0819.EURP192.PROD.OUTLOOK.COM">
      <meta http-equiv="Content-Type" content="text/html;
        charset=windows-1252">
      <meta name="Generator" content="Microsoft Word 15 (filtered
        medium)">
      <style>@font-face
	{font-family:Wingdings;
	panose-1:5 0 0 0 0 0 0 0 0 0;}@font-face
	{font-family:"Cambria Math";
	panose-1:2 4 5 3 5 4 6 3 2 4;}@font-face
	{font-family:Calibri;
	panose-1:2 15 5 2 2 2 4 3 2 4;}@font-face
	{font-family:Verdana;
	panose-1:2 11 6 4 3 5 4 4 2 4;}@font-face
	{font-family:"Segoe UI";
	panose-1:2 11 5 2 4 2 4 2 2 3;}p.MsoNormal, li.MsoNormal, div.MsoNormal
	{margin:0cm;
	font-size:11.0pt;
	font-family:"Calibri",sans-serif;
	mso-fareast-language:EN-US;}a:link, span.MsoHyperlink
	{mso-style-priority:99;
	color:#0563C1;
	text-decoration:underline;}p.MsoListParagraph, li.MsoListParagraph, div.MsoListParagraph
	{mso-style-priority:34;
	margin-top:0cm;
	margin-right:0cm;
	margin-bottom:0cm;
	margin-left:36.0pt;
	font-size:11.0pt;
	font-family:"Calibri",sans-serif;
	mso-fareast-language:EN-US;}span.E-MailFormatvorlage30
	{mso-style-type:personal-compose;
	font-family:"Verdana",sans-serif;
	color:windowtext;
	font-weight:normal;
	font-style:normal;}.MsoChpDefault
	{mso-style-type:export-only;
	mso-fareast-language:EN-US;}div.WordSection1
	{page:WordSection1;}ol
	{margin-bottom:0cm;}ul
	{margin-bottom:0cm;}</style><!--[if gte mso 9]><xml>
<o:shapedefaults v:ext="edit" spidmax="1026" />
</xml><![endif]--><!--[if gte mso 9]><xml>
<o:shapelayout v:ext="edit">
<o:idmap v:ext="edit" data="1" />
</o:shapelayout></xml><![endif]-->
      <div class="WordSection1">
        <p class="MsoNormal"><span lang="EN-US">Hello everyone,<o:p></o:p></span></p>
        <p class="MsoNormal"><span lang="EN-US">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:<o:p></o:p></span></p>
        <p class="MsoNormal"><span
            style="font-size:10.0pt;font-family:&quot;Courier
            New&quot;;color:black;mso-fareast-language:DE" lang="EN-US">  
            Upon receipt of the request at the token endpoint, the
            server<o:p></o:p></span></p>
        <p class="MsoNormal"><span
            style="font-size:10.0pt;font-family:&quot;Courier
            New&quot;;color:black;mso-fareast-language:DE" lang="EN-US">  
            verifies it by calculating the code challenge from the
            received<o:p></o:p></span></p>
        <p class="MsoNormal"><span
            style="font-size:10.0pt;font-family:&quot;Courier
            New&quot;;color:black;mso-fareast-language:DE" lang="EN-US">  
            "code_verifier" and comparing it with the previously
            associated<o:p></o:p></span></p>
        <p class="MsoNormal"><span
            style="font-size:10.0pt;font-family:&quot;Courier
            New&quot;;color:black;mso-fareast-language:DE" lang="EN-US">  
            "code_challenge", after first transforming it according to
            the<o:p></o:p></span></p>
        <p class="MsoNormal"><span
            style="font-size:10.0pt;font-family:&quot;Courier
            New&quot;;color:black;mso-fareast-language:DE" lang="EN-US">  
            "code_challenge_method" method specified by the client.<o:p></o:p></span></p>
        <p class="MsoNormal"><span style="mso-fareast-language:DE"
            lang="EN-US">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.
          </span><span style="mso-fareast-language:DE" lang="EN-US"><o:p></o:p></span></p>
        <p class="MsoNormal"><span style="mso-fareast-language:DE"
            lang="EN-US">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:<o:p></o:p></span></p>
        <p class="MsoNormal"><span style="mso-fareast-language:DE"
            lang="EN-US">Authorization Request:<o:p></o:p></span></p>
        <p class="MsoNormal" style="margin-left:35.4pt"><a
href="https://XXXX/auth?client_id=YYYY&amp;response_type=code&amp;scope=openid+profile&amp;redirect_uri=https://localhost"
            moz-do-not-send="true"><span style="mso-fareast-language:DE"
              lang="EN-US">https://XXXX/auth?client_id=YYYY&amp;response_type=code&amp;scope=openid+profile&amp;redirect_uri=https://localhost</span></a><span
            style="mso-fareast-language:DE" lang="EN-US"><o:p></o:p></span></p>
        <p class="MsoNormal"><span style="mso-fareast-language:DE"
            lang="EN-US">Subsequent Token Request:<o:p></o:p></span></p>
        <p class="MsoNormal" style="margin-left:35.4pt"><span
            style="mso-fareast-language:DE" lang="EN-US">POST /token
            HTTP/1.1<br>
            Host: XXXX<br>
            Content-Length: 256<br>
            <br>
code=ZZZZ&amp;grant_type=authorization_code&amp;client_id=YYYY&amp;redirect_uri=https%3A%2F%2Flocalhost&amp;code_verifier=IqiCQGM06JEyW73AB3f3oblCQKHOorapyqHUcYRujuSikDJx8cvBQ0kmFmzW75uIfaSBtXQrRmwuk71WWO6ryCzahTcxBPYX<o:p></o:p></span></p>
        <p class="MsoNormal"><span style="mso-fareast-language:DE"
            lang="EN-US">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.<o:p></o:p></span></p>
        <p class="MsoNormal"><span style="mso-fareast-language:DE"
            lang="EN-US"><o:p> </o:p></span></p>
        <p class="MsoNormal"><span style="mso-fareast-language:DE"
            lang="EN-US">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
            <a
              href="https://danielfett.de/2020/05/16/pkce-vs-nonce-equivalent-or-not/"
              moz-do-not-send="true">https://danielfett.de/2020/05/16/pkce-vs-nonce-equivalent-or-not/</a>
            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.<o:p></o:p></span></p>
        <p class="MsoNormal"><a name="_Hlk78542542"
            moz-do-not-send="true"><span style="mso-fareast-language:DE"
              lang="EN-US">I think the following mitigations are
              possible:<o:p></o:p></span></a></p>
        <ul style="margin-top:0cm" type="disc">
          <li class="MsoListParagraph"
            style="margin-left:0cm;mso-add-space:auto;line-height:105%;mso-list:l0
            level1 lfo15">
            <span style="mso-bookmark:_Hlk78542542"><span
                style="mso-fareast-language:DE" lang="EN-US">Enforce
                usage of PKCE in the client configuration in the
                Authorization Server<o:p></o:p></span></span></li>
          <li class="MsoListParagraph"
            style="margin-left:0cm;mso-add-space:auto;line-height:105%;mso-list:l0
            level1 lfo15">
            <span style="mso-bookmark:_Hlk78542542"><span
                style="mso-fareast-language:DE" lang="EN-US">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.<o:p></o:p></span></span></li>
          <li class="MsoListParagraph"
            style="margin-left:0cm;mso-add-space:auto;line-height:105%;mso-list:l0
            level1 lfo15">
            <span style="mso-bookmark:_Hlk78542542"><span
                style="mso-fareast-language:DE" lang="EN-US">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).</span></span><span
              style="mso-fareast-language:DE" lang="EN-US"><o:p></o:p></span></li>
        </ul>
        <p class="MsoNormal" style="line-height:105%"><span
            style="mso-fareast-language:DE" lang="EN-US"><o:p> </o:p></span></p>
        <p class="MsoNormal"><span style="mso-fareast-language:DE"
            lang="EN-US">Best regards,<o:p></o:p></span></p>
        <p class="MsoNormal"><span style="mso-fareast-language:DE"
            lang="EN-US"><o:p> </o:p></span></p>
        <p class="MsoNormal" style="margin-bottom:12.0pt"><span
style="font-size:10.0pt;font-family:&quot;Verdana&quot;,sans-serif;color:black;mso-fareast-language:DE"
            lang="EN-US">Benjamin Häublein<br>
          </span><span
style="font-size:10.0pt;font-family:&quot;Verdana&quot;,sans-serif;color:black;mso-fareast-language:DE"
            lang="EN-US">Senior Consultant<br>
            <br>
            cirosec GmbH<br>
            Ferdinand-Braun-Strasse 4<br>
            74074 Heilbronn<br>
            Germany<br>
            Phone: +49 (7131) 59455-74<br>
            Fax: +49 (7131) 59455-99<br>
            Mobile: </span><span
style="font-size:10.0pt;font-family:&quot;Verdana&quot;,sans-serif;color:black;mso-fareast-language:DE"
            lang="EN-US">+49 (151) 122414-74<br>
          </span><span
style="font-size:10.0pt;font-family:&quot;Verdana&quot;,sans-serif;color:black;mso-fareast-language:DE"
            lang="EN-US"><a class="moz-txt-link-abbreviated" href="http://www.cirosec.de">www.cirosec.de</a><br>
            <br>
            HRB Stuttgart 107883<br>
            CEO Stefan Strobel, CFO Peter Lips</span><span
style="font-size:10.0pt;font-family:&quot;Verdana&quot;,sans-serif;color:black;mso-fareast-language:DE"
            lang="EN-US"><o:p></o:p></span></p>
        <p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p>
      </div>
      <br>
      <fieldset class="mimeAttachmentHeader"></fieldset>
      <pre class="moz-quote-pre" wrap="">_______________________________________________
OAuth mailing list
<a class="moz-txt-link-abbreviated" href="mailto:OAuth@ietf.org">OAuth@ietf.org</a>
<a class="moz-txt-link-freetext" href="https://www.ietf.org/mailman/listinfo/oauth">https://www.ietf.org/mailman/listinfo/oauth</a>
</pre>
    </blockquote>
    <p><br>
    </p>
    <pre class="moz-signature" cols="72">-- 
<a class="moz-txt-link-freetext" href="https://danielfett.de">https://danielfett.de</a></pre>
  </body>
</html>

--------------B31A28B35D92BE8613BA2A1C--

