Re: [OAUTH-WG] I-D Action: draft-ietf-oauth-selective-disclosure-jwt-06.txt

Neil Madden <neil.e.madden@gmail.com> Thu, 26 October 2023 13:03 UTC

Return-Path: <neil.e.madden@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 EDC05C15152F for <oauth@ietfa.amsl.com>; Thu, 26 Oct 2023 06:03:15 -0700 (PDT)
X-Virus-Scanned: amavisd-new at amsl.com
X-Spam-Flag: NO
X-Spam-Score: -6.213
X-Spam-Level:
X-Spam-Status: No, score=-6.213 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_MESSAGE=0.001, MIME_HTML_ONLY=0.1, MIME_HTML_ONLY_MULTI=0.001, MIME_QP_LONG_LINE=0.001, MPART_ALT_DIFF=0.79, RCVD_IN_DNSWL_HI=-5, RCVD_IN_ZEN_BLOCKED_OPENDNS=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01, URIBL_DBL_BLOCKED_OPENDNS=0.001, URIBL_ZEN_BLOCKED_OPENDNS=0.001] autolearn=ham autolearn_force=no
Authentication-Results: ietfa.amsl.com (amavisd-new); dkim=pass (2048-bit key) header.d=gmail.com
Received: from mail.ietf.org ([50.223.129.194]) by localhost (ietfa.amsl.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id k0inYDOcc3w5 for <oauth@ietfa.amsl.com>; Thu, 26 Oct 2023 06:03:12 -0700 (PDT)
Received: from mail-lj1-x234.google.com (mail-lj1-x234.google.com [IPv6:2a00:1450:4864:20::234]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by ietfa.amsl.com (Postfix) with ESMTPS id 2E611C14F736 for <oauth@ietf.org>; Thu, 26 Oct 2023 06:03:12 -0700 (PDT)
Received: by mail-lj1-x234.google.com with SMTP id 38308e7fff4ca-2c508e76eb4so2294391fa.0 for <oauth@ietf.org>; Thu, 26 Oct 2023 06:03:12 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1698325390; x=1698930190; darn=ietf.org; h=cc:to:date:message-id:subject:mime-version :content-transfer-encoding:from:from:to:cc:subject:date:message-id :reply-to; bh=tcJdo4V10POlWVDp286AM9X5aNe2XIJueEsjfBHKjjk=; b=nl1KjhcHQRhEPqzA7hdhRSeDzbnveNHLr0egTBxamRw/uw76qysd+zDnc8Yjsp+eto qZXWeRgqu2b8+gsiH/t0MbXI8WEyj0oHyXdjbXX1iaKI+P9aLcvW9zKGxqDBpBUEW1gD wI1fMY6B9p0XBCFFSNUS0ATVZYRKp3fkNCcW1w0RCC+fsvc+oQYJexSQ855W6Z++aTKU BheoJvga+BO9BTl/C5gWSGdxfnihxE05jL2L5o+vW/A/nGw1XEY9vG4oXE9xHJ0INyVG 14xJ9V7wQ8iI1iFUlcxZ07UWH31REjTOGOSNBHYQHLQdGgw7qvO03KX9svy4A5P54XKJ zQ/g==
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1698325390; x=1698930190; h=cc:to:date:message-id:subject:mime-version :content-transfer-encoding:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=tcJdo4V10POlWVDp286AM9X5aNe2XIJueEsjfBHKjjk=; b=NmR2i8ODKPXOTG48l/71x84FFIbrdOEuJod3kRjL8E+y8YrTwyX45TyTQ6ot7Um6PT HJdHwyHPVw2lO9NuQ33PSNLCKDXMVdJrr/tim5cDn0YoasokdOhNt9SjOP5V/H3+n1VH l8gfvpdcxlgBKbg64FvJueO4lO3NlUv+FwDJK/gNNOqG3YqBHAIWymtRsLCdiZ5fi6fN gaYaWHPkiOOdri3dgXR0pNmSuaiepJB9wVvNY0sx23ojxNyzmBkUkjXa5Kxcb+kH+eTY VVvz51wlvOYLdfxwM4fiOJ/kAorPPxjfTazvAxgHil6TRLuz7/LJE6CZI2etTrcK2YN1 lWrg==
X-Gm-Message-State: AOJu0YzBwbyyqYTJwKkXqgBK2wm+cHD3onISUzY1j5/K/fGbRJ8eTO8e UsJ+a8MTrE/TngGBv2brphTTRGz0A+g=
X-Google-Smtp-Source: AGHT+IE1y8eeV5/fG45QeUvkxUpvklpPDVGg86aoXjyXi6ztMbptkMMBFgQozLYUikzMVUURVJdB0A==
X-Received: by 2002:a2e:b0f7:0:b0:2c5:519:bb1b with SMTP id h23-20020a2eb0f7000000b002c50519bb1bmr12187751ljl.2.1698325389507; Thu, 26 Oct 2023 06:03:09 -0700 (PDT)
Received: from smtpclient.apple ([213.31.127.213]) by smtp.gmail.com with ESMTPSA id q10-20020a7bce8a000000b003fc16ee2864sm2442475wmj.48.2023.10.26.06.03.08 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Thu, 26 Oct 2023 06:03:08 -0700 (PDT)
From: Neil Madden <neil.e.madden@gmail.com>
X-Google-Original-From: Neil Madden <Neil.E.Madden@gmail.com>
Content-Type: multipart/alternative; boundary="Apple-Mail-0D6D5776-76B9-43BD-8DFF-68FC62F59D4C"
Content-Transfer-Encoding: 7bit
Mime-Version: 1.0 (1.0)
Message-Id: <61DA17C1-8CFA-429F-A031-57E50A294908@gmail.com>
Date: Thu, 26 Oct 2023 14:02:57 +0100
To: Brian Campbell <bcampbell@pingidentity.com>
Cc: oauth <oauth@ietf.org>
X-Mailer: iPhone Mail (20G75)
Archived-At: <https://mailarchive.ietf.org/arch/msg/oauth/rPitG7FvJcVEyIcAwn0bXzGToGM>
Subject: Re: [OAUTH-WG] I-D Action: draft-ietf-oauth-selective-disclosure-jwt-06.txt
X-BeenThere: oauth@ietf.org
X-Mailman-Version: 2.1.39
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: Thu, 26 Oct 2023 13:03:16 -0000


On 25 Oct 2023, at 22:00, Brian Campbell <bcampbell@pingidentity.com> wrote:


Thanks for the comments and questions Neil. With the help of the draft co-authors, I've tried to reply (probably inadequately!) inline below.

Thanks. Some responses below. 

On Tue, Oct 24, 2023 at 3:48 AM Neil Madden <neil.e.madden@gmail.com> wrote:
I’ve had a look through this new draft and I have some comments and questions. Some of which are similar to comments I already raised [1], but haven’t been addressed.

Are we concerned about Holders and Issuers colluding?

With SD-JWT or plain JWT or really any similar signed token construct the Verifier has to trust the Issuer ultimately to act/issue honestly. So colluding Holders and Issuers just isn't part of the threat model. I don't honestly know how that could be different. The Issuer, if malicious, can issue a token with whatever content they want.

That’s reasonable. 

 
For example, now that claim names are blinded an Issuer can add the same claim multiple times with different, potentially contradictory, values and then the Holder can selectively release one disclosure to one Verifier and a completely different one to another Verifier. This seems problematic at least, that the “same” credential could be interpreted differently by different parties.

A well behaving Holder would reject such a credential based on the verification and processing rules (https://www.ietf.org/archive/id/draft-ietf-oauth-selective-disclosure-jwt-06.html#section-8.1-4.3.2.3.2.2.2.3" target="_blank" rel="nofollow">this one specifically). While malicious Issuers and colluding Holders and Issuers are outside the threat model for the reasons explained above. So this situation is handled as much as it can be (as best I know anyway) in the draft.

A more sophisticated version of this “attack” illustrates the need for collision resistance in the hash function, not just preimage resistance as stated in the draft (and already raised by me in [1]). If the hash is not CR then a malicious Issuer can find colliding [salt, key, value] triplets that have the same hash value, give one to the Holder and then later claim that they actually signed the other one. (This is not just theoretical, similar attacks have been used to create fraudulent SSL certificates [2]).

The draft currently says that second-preimage resistance is needed, which prevents a malicious Holder from finding a different Disclosure value that results in a digest that's the same as one in the signed credential. Protecting against a malicious user effectively forging or modifying disclosed claim names/values is the security objective. Second-preimage resistance is not as strong as collision resistance but I believe is correct and sufficient for the context of use. And a malicious Issuer isn't something that's in scope and could do all kinds of other bad things. This is the section of the security considerations with that:
https://www.ietf.org/archive/id/draft-ietf-oauth-selective-disclosure-jwt-06.html#section-11.5" target="_blank" rel="nofollow">https://www.ietf.org/archive/id/draft-ietf-oauth-selective-disclosure-jwt-06.html#section-11.5

Ok, that is a fair enough stance. Without requiring collision resistance though it does make SD-JWT a slightly weird signature scheme, in that the issuer is not actually committed to the contents of the token like they would be for a normal signed JWT. That is a surprising property. For example, if you store SD-JWTs for audit trail purposes (as some people do for normal JWTs), the contents are potentially repudiable. Like you say, if you trust the issuer then maybe that is fine, but it’s a sharp edge that maybe it would be better to remove? Given that pretty much any hash function that is likely to be used with SD-JWT will almost certainly be CR anyway. 

This also indicates that the security strength of the signature scheme is bounded by the collision resistance of the hash function - e.g. there’s little point using ES512 with SHA-256, for example. Probably the security considerations should suggest matching hash functions to signature algorithms.

Yeah, saying something about matching the strength of hash function and signature algorithm would probably be worthwhile.

Yes, or just pick SHA-512…

Furthermore, preimage resistance is not a sufficient property to ensure confidentiality of withheld claims. Preimage resistance holds if the attacker cannot recover the exact input that produced a given hash value, but it doesn’t preclude the attacker being able to recover partial information about that value. For example, consider the hash function H(x) = SHA-256(x) || x[x.len-10..x.len] (where || is concatenation). This hash function when applied to SD-JWT is preimage resistant (assuming the salt is strong), but leaks the last 10 bytes of the claim value.

Preimage resistance maybe isn’t the term to use there. It’s used in https://www.ietf.org/archive/id/draft-ietf-oauth-selective-disclosure-jwt-06.html#section-11.5" target="_blank" rel="nofollow">that section-11.5 along with some text that says that it needs to be “infeasible to calculate the salt and claim value that result in a particular digest”.  We are trying to say that the hash has to have the property that it can’t be reversed (or even partially reversed, to your point). There’s probably a better way to state that the hash function has to be not at all reversible. Can you perhaps suggest some text? Or could we just replace “preimage resistant” with “irreversible” in that text in 11.5? And maybe qualify that text a bit more too with something like “infeasible to calculate the salt and claim value (or any portion thereof) that results in a particular digest”.

That latter text seems a pretty good start to me. Part of the terminology problem I think is that SD-JWT is couched in terms of signatures but actually its primary security goal is confidentiality. As I said, I think the correct formal security notions come from the work on commitment schemes, which are “binding” and “hiding”. The hiding property is what you want here - it basically says that it’s infeasible for an attacker to learn anything about the message from the hash that they couldn’t already infer without the hash. 

The binding property is maybe too strong if we trust the issuer - it would require collision-resistance as I’ve said. There is a paper (https://eprint.iacr.org/2017/664" rel="nofollow">https://eprint.iacr.org/2017/664) which distinguishes between “sender-binding” and “receiver-binding”, which sounds similar to what you want to express: trusted issuer, potentially untrusted holder/verifiers. However, I think the receiver binding notion is still too strong and would also require collision resistance. I’ll see if I can dig something up and suggest some wording. 

Your wording does look pretty good though so maybe we don’t need to be too formal about this?

<snip> 

The draft repeatedly says that a symmetric signature algorithm (MAC) must not be used. Perhaps I’m missing something here, but why not? It doesn’t seem like it compromises any of the intended security properties. Use of a symmetric MAC may also limit the privacy impacts on users as it provides some measure of deniability (similar to that mentioned in section 12.1), as any Verifier in possession of the secret key could also have produced any claims that are subsequently leaked, allowing the user to deny that they were produced by the supposed Issuer. (This deniability property holds even without subsequent leaking of old signing keys).

The thinking behind that was basically that this Issuer-Holder-Verifier model implies/assumes that an Issuer issues a token with no idea of where it’ll be presented and having a shared symmetric key seemed really weird in that situation. Also had to explain why or how a shared symmetric key would work in that situation too. That said, there’s been some talk about loosening that restriction - largely around the same reasoning on deniability that you cite - I guess your comment here should be taken as supportive of that prospective change?

Yes. 


The security considerations about salt entropy should probably reference RFC 4086 (BCP 106) or something more up to date (maybe RFC 8937 too).

Good point, yeah.
 

I think section 11.8 about selectively disclosing contraints on the use of a SD-JWT is completely inadequate and will almost certainly lead to attacks. Requiring Verifiers to hard-wire the set of constraints they enforce is likely to be damaging to future evolution of the standard as new security constraints are added. It would seem especially problematic to allow selective disclosure of a “cnf” claim for example, and yet nothing forbids it and the history of JWT usage suggests that anything not forbidden will at some point happen (and even some things that are forbidden). I suggest establishing a registry of claims that are really usage constraints and forbidding issuers from allowing anything in that list to be selectively-disclosed. (There are perhaps some exceptions here, e.g. “aud” is a constraint in this sense but it probably _does_ make sense for it to be selectively disclosed, but only on a per-array-item basis: that way a Holder cannot remove the constraint entirely but can still hide other “recipients”).


It is admittedly a potentially fraught area. But I’d argue that having a hard-wired set of claims/constraints enforced/required by verifiers is appropriate and necessary even when selective disclosure isn’t at play. It’s how regular JWT works (or should work) in practice already. And don’t think it harms future evolution because any new security constraints would necessarily need updates all around because they won’t be understood otherwise.

What I want to ensure is that a migration path like the following works:

1. at some future point in time the WG becomes aware of attack A and develops backwards-compatible mitigation M (think PKCE for example)

2. verifiers roll out support for M

3. issuers/holders gradually roll out support for M

Between steps 2 and 3 there can be verifiers that support the enhanced security but are dealing with a mixture of clients that do or do not support the new mitigation. This is where hard-coded requirements in the verifiers can cause issues, because it means you can’t turn on the new mitigation until all clients support it. Or the verifiers have to have complex rules about which clients support some mitigation and which don’t (a la user-agent sniffing). 

It’s much better to say “if there’s a code_challenge (or cnf or …) on this request then enforce it”. 


The 11.8 section could perhaps be stronger in saying that claims controlling the validity of the token shouldn’t be made selectively disclosable. But what exactly constitutes such a claim is actually rather murky and there are undoubtedly exceptions like you point out with “aud”.

It may be murky but I think we do need to try and look at this. I’m happy to think about some text to suggest here. 

And I know some have expressed the need/desire to have key/holder binding type claims (such as “cnf” but not only that) be made selectively disclosable for privacy reasons.

Making cnf selectively disclosable seems like a security disaster to me. It means that if an attacker steals such a token they can basically treat it as a bearer token and not disclose that it is key-bound. (Unless the verifiers enforce only key-bound tokens, which can be difficult as I’ve said). My prediction is that if we allow this it will cause security issues. 

I also don’t think a new registry would really help the situation.  At this level we're describing a generic mechanism and don’t necessarily even have a list of all claims that could be interpreted as constraints in a particular context or application. Note, for example though, that https://datatracker.ietf.org/doc/draft-ietf-oauth-sd-jwt-vc/" target="_blank" rel="nofollow">https://datatracker.ietf.org/doc/draft-ietf-oauth-sd-jwt-vc/ does say that certain claims must be included directly and not made selectively disclosable.  

Which leads back to ultimately needing that requirement that Verifiers ensure that all the claims they deem necessary are present (in the clear or disclosed) when checking the validity and accepting the token.

Which I think harms future evolvability. I don’t think it would be too hard to add a new column to the IANA JWT standard claims list to indicate selective disclosability - “allowed”, “never”, “per-item” or something like that. 

 
On a related note, section 11.6 says that to avoid this kind of attack, Verifiers MUST NOT take into account whether a Key Binding is present or not to decide whether to require Key Binding. This seems to preclude Verifiers that can handle different levels of access with different security requirements and is the sort of requirement that makes it near impossible to incrementally evolve tougher security requirements over time. It effectively becomes an all-or-nothing switch that will have the likely effect of making the use of Key Binding less attractive. Security hardening should be the easy path if we want to see it adopted.


It’s not meant to preclude that kind of thing (and reading it again, I don’t think it does preclude it). But rather to just say that whatever the Verifier’s requirements on key binding are have to be based on its policy and not on the content of the token (some of which could be manipulated by the holder). A Verifier’s policy could, as you describe, afford different levels of access based on different security characteristics of the presented token/credential. Or the Verifier’s requirements could, for example, say that for credential type A, Key Binding is always required, while for credentials of type B, it is only required when the credential was issued by an issuer that is known to issue credentials supporting Key Binding.

This assumes that the issuer is not selectively discloseable…

— Neil