Hi Neil,

Thank you again for your review and the follow up. Please see my comments in-line.

        ā€¸Yaron


Hi Mike,

I sent this originally back in June last year, I can see some of these points 
have been addressed in -01, but not others, so I will include further comments 
in-line below. (Apologies if I missed replies - I?ve realised a few messages 
from this WG have ended up in my spam folder).

As a general point, the BCP is for JWT, but some of the advice (and my points 
below) apply more generally to other JOSE objects (as pointed out in the 
introduction). Should this be reflected in the title?


On 4 Jun 2017, at 15:11, Neil Madden <neil.mad...@forgerock.com> wrote:

I originally set this message just to the BCP authors. As requested by Mike 
Jones, I am sending it here too:

Hi,

I've just seen this draft best-practice guide for JWTs pop up. I have a number 
of suggestions for improvements. Mostly, I think the advice is good but should 
be spelt out a bit more clearly. Here are some suggestions:

1. Explicitly spell out the ECDH-ES public key validation routines from NIST. I 
have a blog post summarising them: 
https://neilmadden.wordpress.com/2017/05/17/so-how-do-you-validate-nist-ecdh-public-keys/

To be clear here, I think section 3.4 (Validate Cryptographic Inputs) should 
have text along the lines of the following added:

?ECDH-ES ephemeral public key (epk) inputs should be validated according to the 
recipient?s chosen elliptic curve. For NIST prime-order curves P-256, P-384 and 
P-521, validation MUST be performed according to Section 5.6.2.3.4 ?ECC Partial 
Public-Key Validation Routine? of NIST Special Publication 800-56A revision 3 [1]. 
Where the X25519 or X448 curves of RFC 8037 [2] are used, then the implementation 
MAY reject any ephemeral public key that produces an all-zero ECDH shared secret as 
per RFC 7748 Section 6 [3]."

[1] https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-56Ar3.pdf
[2] https://tools.ietf.org/html/rfc8037
[3] https://tools.ietf.org/html/rfc7748#section-6

I should note that the final sentence about validating X25519/X448 public keys 
is not without some controversy. See 
https://moderncrypto.org/mail-archive/curves/2017/000896.html for a rabbit-hole 
discussion together with associated links.

I do not feel confident to say what the right answer is for those curves - 
whether to validate at all, and if so whether to blacklist bad public keys or 
check for an all-zero shared secret. Perhaps we should get CFRG input on this 
point? Or should we take RFC 7748 as being the considered CFRG opinion on this 
topic (and so copy the ?MAY? wording)?

I think a MAY check is useless in practice, and also, the link you mention argues quite convincingly against the 25519 check. So I propose to adopt the first part of your text.


2. Recommend that (despite the -ES) ECDH is safest when *both* keys are 
ephemeral (eg you use some initial step to retrieve a fresh authenticated 
ephemeral key from the other party).

I think this comment is not necessary in hindsight. While fully-ephemeral ECDH 
has some advantages (as does static-static in some cases, e.g. NaCl 
crypto_box), it?s a more complicated discussion. For this BCP it is best to 
concentrate on ECDH-ES as specified and ensure that implementations perform 
proper validation of ephemeral public keys.


Agree.

3. Spell out how to authenticate ECDH ephemeral keys. For instance, include an 
inner signed JWT that repeats the epk and possibly the apu/apv claims too.

This is probably a more general point that none of the public-key encryption 
modes in JOSE are authenticated. If sender authentication is required then 
nested signed-and-encrypted objects should be used.


Yes, and it's not up to the BCP to add new authenticated modes.

4. Recommend that the apu and apv claims as a bare minimum include a hash of 
both public keys and SHOULD include any other known identifiers.

I'm not clear about "apu" in the general use case for JWT, where the identity of the recipient of a JWT is not known in advance to the sender.

Also, RFC 7518 uses "Alice" and "Bob" in these claims, and does not include any hashes. (And see my next comment).


Section 5.8.2 of NIST SP.800-56A rev 3 (referenced in point 1 above) gives some 
advice on the kinds of things that should be included here. Appendix B of the 
same document provides some rationale for why this should be done, as does RFC 
7748 Section 7 (Security Considerations). RFC 7518 (JWA) Section 4.6.2 already 
normatively references NIST SP.800-56A, but only for ?applications wishing to 
conform to [NIST.800-56A]?. In my opinion, this should be strengthened in this 
BCP to a SHOULD/RECOMMENDED.

5. Recommend that the receiving party recalculates the apu and apv claims from 
known inputs to check they match. (Or leave these out of the JWT and require 
the other party to recalculate them).

But this would require normative language on the contents of these claims, which does not appear in existing RFCs. I would hesitate to include such language in a BCP. There must be a very good reason for a BCP to make existing implementations non-conformant.

6. Provide explicit key lifetime requirements. E.g., for AES GCM this should 
not exceed 2^32 messages for randomly-generated IVs, and not exceed 2^64 
*blocks* in total (so unless you restrict JWT lengths to less than 2^32 blocks 
and use a message counter as IV then this also limits to 2^32 messages). For 
CBC it should not exceed 2^48 messages.

I withdraw this comment, RFC 7518 Section 8.2 already addresses this point.

7. Require that the "alg" and "enc" claims are ONLY used to reject unexpected algorithms, NEVER to 
select an algorithm (even amongst a "supported" set). Cryptographic agility should be achieved by using 
"kid" claims that reference one of a set of known keys and the key should specify the algorithm (either 
explicitly or by the key parameters/size).

I think this is now adequately addressed by section 3.1.

8. Deprecate or strongly recommend against all of the RSA encryption modes 
except OAEP-256.

Yes. What about RSA with/without PSS?

9. Strongly discourage any use of compression with encrypted JWEs - it is too 
easy to leak sensitive information.
10. Recommend that if a JWE is used to encrypt a password or other value for 
which knowing the length may be a weakness, that such fields are explicitly 
padded by the application or at least use CBC mode to reduce the amount of 
length information leaked to a multiple of the AES block size.

These last two points are related: encryption hides everything apart from the 
length of a plaintext. Compression varies the length based on the content. The 
combination of the two weakens the security of the encryption, but the length 
may already be sensitive. Applications should consider what information might 
be leaked in these cases and make informed decisions about whether to pad or 
compress content before encryption.

Agree.


11. Require constant-time comparisons of HMAC tags.

This point is already covered by RFC 7518 Section 3.2.

12. Recommend using deterministic ECDSA signatures as described in RFC 6979 to 
minimise the risk of leaking the private key.

I'm not sure how this would interact with JWE. I suspect these signatures would have to be defined as a new algorithm (so out of scope for the BCP).

13. Recommend that if the ECDH calculation produces an all-zero shared secret 
that this is rejected.

This is covered in my suggestion in point 1.

14. Never produce a signed JWT containing a "sub" claim unless you are 
explicitly vouching for the identity of that subject. It is far too easy to accidentally 
produce valid OIDC id tokens from unrelated code!

I think this is now covered by the section on explicit typing.

Explicit typing is a welcome addition. A complementary approach would be to 
recommend using different cryptographic keys for different types of JWTs. One 
way to achieve this for symmetric algorithms or ECDH would be to use a 
key-derivation function to derive unique keys based on some domain separation 
string.

I find the discussion in section 3.2 about the ?none? algorithm unnecessary for 
the BCP. I would say using ?none? should not be a recommended best practice.

A colleague recently shared this pen-tester JWT cheat-sheet with me: 
https://assets.pentesterlab.com/jwt_security_cheatsheet/jwt_security_cheatsheet.pdf
 which hints at a few other points worth mentioning (I can draft text for these 
if you wish):

- If the ?kid? header is used to perform a lookup in a database then there is a 
risk of SQL/LDAP injection if the value is not validated first or appropriate 
interfaces used (e.g. prepared statements).
- The ?jwk? header should not be directly trusted, but only ever used to match 
a known key.

I agree about kid and jku, but I'm not familiar with all valid use cases of "jwk" so would appreciate more opinions regarding this statement.

Likewise, I?d say the ?jku? header should really be matched against a known whitelist before being trusted, as it might additionally lead to SSRF attacks if the server can be tricked into loading arbitrary URLs.

Kind regards,

Neil


---

_______________________________________________
OAuth mailing list
OAuth@ietf.org
https://www.ietf.org/mailman/listinfo/oauth

Reply via email to