Re: [OAUTH-WG] Token substitution in DPoP

Neil Madden <neil.madden@forgerock.com> Tue, 24 November 2020 11:03 UTC

Return-Path: <neil.madden@forgerock.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 1323B3A03FA for <oauth@ietfa.amsl.com>; Tue, 24 Nov 2020 03:03:00 -0800 (PST)
X-Virus-Scanned: amavisd-new at amsl.com
X-Spam-Flag: NO
X-Spam-Score: -0.198
X-Spam-Level:
X-Spam-Status: No, score=-0.198 tagged_above=-999 required=5 tests=[DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, HTML_MESSAGE=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-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=forgerock.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 M4umliGTAisT for <oauth@ietfa.amsl.com>; Tue, 24 Nov 2020 03:02:57 -0800 (PST)
Received: from mail-ej1-x634.google.com (mail-ej1-x634.google.com [IPv6:2a00:1450:4864:20::634]) (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 AC92C3A03F8 for <oauth@ietf.org>; Tue, 24 Nov 2020 03:02:55 -0800 (PST)
Received: by mail-ej1-x634.google.com with SMTP id f23so27880923ejk.2 for <oauth@ietf.org>; Tue, 24 Nov 2020 03:02:55 -0800 (PST)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=forgerock.com; s=google; h=from:mime-version:subject:date:message-id:references:cc:in-reply-to :to:content-transfer-encoding; bh=7dainsuyIqHPus+ChICt2sff+y5SPpu7mrvhWu7xODU=; b=BfCSNCgiXXSjpd9dUcPs1hQ7zlM4rVdOaJkeX+Q+tpV1cvxj96Q/AZu+tznWQflct3 NoB7Tny7RQLJwroFtFASnyrVyPCMqc8kVbKK/OHX9AWstSPON68PSFNKfMWmfm7uPXcu Ht+jr7Aw5PT59P8EJr8MTlZvBPSyD9Xo5/UyM=
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:mime-version:subject:date:message-id :references:cc:in-reply-to:to:content-transfer-encoding; bh=7dainsuyIqHPus+ChICt2sff+y5SPpu7mrvhWu7xODU=; b=lgcEca78CJuG8qY2UIaJwpCfU830X/0WPw4g9PHPP2ezeYoQ6kxyxXLtfeAknn0fFZ At8x1AR5gr0am6OkXS1Q1jNKSOAkn+oKQg0uxpbhW9WVDtdzgXJGf6PplG8PENTME9sq cULK3o9OnfL3ZVxj9aQkQOwzMzZTlkcwzNWsE8uDlv6FAAo78VpY66GS63B53L3oyRKC MpoYdB1c0qfMszryGCtFZI/NmvTnoy5CbdITsAhzZCZBlDPm7rbq/DBxip8mkMigyAX7 S5Hd+cKmR/DW1odbC5I0ue0iCy7HtidbvFDWs5ePGVXC05OEyv5qyF259NAD7TLs4vnO uTMQ==
X-Gm-Message-State: AOAM531g+8HNnog7KAimpWkuVRqnRRZ0Wzb/9/SxfUjMq6siYXoV5GK5 Z74h5LueKFQBWNVF8mCyWQFqetm26mUdm882DVLqFMwHoLGmw+2hr/913I96l/86T0usjmSaIN9 fI7RHnbuC
X-Google-Smtp-Source: ABdhPJw7eMoewRaDoWMv1MAWJ/iTPyIGIi6WdjEhuGFyZ+dqbviUvw2jWzIQ4y7sc3SCToSAZ9p6Jg==
X-Received: by 2002:a17:906:1db1:: with SMTP id u17mr2693129ejh.359.1606215774366; Tue, 24 Nov 2020 03:02:54 -0800 (PST)
Received: from [10.0.0.17] ([213.31.218.193]) by smtp.gmail.com with ESMTPSA id t10sm6601530eji.61.2020.11.24.03.02.53 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Tue, 24 Nov 2020 03:02:53 -0800 (PST)
From: Neil Madden <neil.madden@forgerock.com>
Mime-Version: 1.0 (1.0)
Date: Tue, 24 Nov 2020 11:02:52 +0000
Message-Id: <22D724F4-BF92-481F-A70C-E82B08D2017F@forgerock.com>
References: <c3e0e841-0e30-872e-a56f-330c0b897da0@danielfett.de>
Cc: oauth@ietf.org
In-Reply-To: <c3e0e841-0e30-872e-a56f-330c0b897da0@danielfett.de>
To: Daniel Fett <fett@danielfett.de>
X-Mailer: iPhone Mail (18A8395)
Content-Type: multipart/alternative; boundary="Apple-Mail-4FA33979-B5F8-4764-B602-BD44E3FF5ADF"
Content-Transfer-Encoding: 7bit
Archived-At: <https://mailarchive.ietf.org/arch/msg/oauth/aAkom9fsZAjSSJW8vLzoNtuHWHg>
Subject: Re: [OAUTH-WG] Token substitution in DPoP
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: Tue, 24 Nov 2020 11:03:00 -0000

I agree with Daniel that I’d be a bit wary of assuming that this could never be exploited. For example, a server-side web app that signs DPoP proofs on behalf of client-side Javascript (to keep the key safe on the server) and reuses the key for different users could be a risk. 

IMO this is another symptom of the general issue of using signatures for authentication - they are too strong for the job. The fact that a signature is equally valid to all parties and at all times means you have to be very careful to include enough context in the signature calculation to ensure all these kinds of attacks are eliminated. And you have to ensure that all RSes check the context. 

Contrast that to my suggestion to use ECDH [1], which was already immune to such attacks by including the access token in the key derivation step. (And in such a way that requires no additional data on the wire and is almost impossible for the RS not to verify). Even without including the access token in the KDF, the attack could only happen if the client reused its key and the RS reused a challenge key pair. 

Macaroon access tokens [2] are also immune to this attack, as in that case the constraints that go in the DPoP proof are directly attached to the access token itself so there is no way to reuse them separately. (Interestingly, macaroons have a more direct analogue of DPoP in the form of discharge macaroons. Such discharge macaroons are required to be “prepared” before use, which cryptographically binds them to the equivalent of the access token - so this kind of attack was also considered and addressed there). 

[1]: https://mailarchive.ietf.org/arch/msg/oauth/1Zltt75p5taPw0DRmhoKLbavu9s/
[2]: https://neilmadden.blog/2020/07/29/least-privilege-with-less-effort-macaroon-access-tokens-in-am-7-0/

— Neil

> On 24 Nov 2020, at 09:38, Daniel Fett <fett@danielfett.de> wrote:
> 
> 
> Thanks Justin for bringing this to our attention.
> 
> Right now, I don't think that this is a big problem and I wasn't able to come up with a way to improve the attack. I hope that it doesn't come back to haunt us when somebody does a more in-depth analysis...
> 
> That said, the lack of binding to the access token makes it easier to precompute proofs if somebody has a limited code execution opportunity in the client. We have this paragraph in the spec:
> 
>    Malicious XSS code executed in the context of the browser-based
>    client application is also in a position to create DPoP proofs with
>    timestamp values in the future and exfiltrate them in conjunction
>    with a token.  These stolen artifacts can later be used together
>    independent of the client application to access protected resources.
>    The impact of such precomputed DPoP proofs can be limited somewhat by
>    a browser-based client generating and using a new DPoP key for each
>    new authorization code grant.
> 
> The recommendation could be to use a fresh key pair for each token request.
> 
> -Daniel
> 
> 
> Am 20.11.20 um 20:26 schrieb Justin Richer:
>> While working on an implementation of DPoP recently, I realized that the value of the access token itself is not covered by the DPoP signature at all. What I’m wondering is whether or not this constitutes an attack surface that we care about here. Here’s how it works:
>> 
>> 
>> Let’s say that a client creates a DPoP key and uses that key to request two tokens, T1 and T2, for different users, Alice and Bob, respectively. Alice is malicious and wants to get Bob’s stuff. Alice manages to get a hold of Bob’s token value, T2, through some means. Normally DPoP wouldn’t let Alice create a new request using T2 since Alice doesn’t have the client’s key. However, if Alice gets the client to create a request for her using T1, she can copy the signature from that request onto a new request using T2. Since the signature doesn’t cover the token value and the key is the same, the RS should accept both requests, right?
>> 
>> An important aspect is that the parts needed to make this attack work are a little weird: you’d need access to a valid signed request from the client with T1 as well as access to a valid T2 attached to the same key in order to make this substitution. However, this is effectively the same attack area that bearer tokens have in a lot of ways, since it doesn’t require the attacker gaining access to the singing key to generate or modify a signature, nor does it require the attacker to generate or modify an access token (merely obtain one).
>> 
>> 
>> I’d like to understand if this is an actual attack against DPoP. If it isn’t, how is it countered by DPoP today? If it is, do we discuss in the DPoP draft? I didn’t see a mention of it there. If it’s not, should we discuss it there?
>> 
>> 
>> The old OAuth PoP draft mitigates this attack by putting the access token itself inside the signature body instead of a second header. Another option would be to include a hash of the token value (such as OIDC’s “at_hash” method used in ID Tokens) in the DPoP payload. With either of these approaches, Alice having access to T1, T2, and a signed message for T1 does not allow her to use T2 effectively.
>> 
>>  — Justin
>> _______________________________________________
>> OAuth mailing list
>> OAuth@ietf.org
>> https://www.ietf.org/mailman/listinfo/oauth
> 
> -- 
> https://danielfett.de
> _______________________________________________
> OAuth mailing list
> OAuth@ietf.org
> https://www.ietf.org/mailman/listinfo/oauth

-- 
ForgeRock values your Privacy <https://www.forgerock.com/your-privacy>