Skip to content

[SECURITY] Algorithm Confusion Through kid Header #274

Description

@paragonie-security

Starting here:

python-jose/jose/jws.py

Lines 250 to 258 in be8e914

def_verify_signature(signing_input, header, signature, key="", algorithms=None):
alg=header.get("alg")
ifnotalg:
raiseJWSError("No algorithm was specified in the JWS header.")
ifalgorithmsisnotNoneandalgnotinalgorithms:
raiseJWSError("The specified alg value is not allowed")

This correctly rejects invalid alg headers, as JWT implementations MUST to be secure.

python-jose/jose/jws.py

Lines 259 to 262 in be8e914

keys=_get_keys(key)
try:
ifnot_sig_matches_keys(keys, signing_input, signature, alg):
raiseJWSSignatureError()

However, the algorithm associated with the key returned from _get_keys() is not validated.

python-jose/jose/jws.py

Lines 217 to 247 in be8e914

def_get_keys(key):
ifisinstance(key, Key):
return (key,)
try:
key=json.loads(key, parse_int=str, parse_float=str)
exceptException:
pass
ifisinstance(key, Mapping):
if"keys"inkey:
# JWK Set per RFC 7517
returnkey["keys"]
elif"kty"inkey:
# Individual JWK per RFC 7517
return (key,)
else:
# Some other mapping. Firebase uses just dict of kid, cert pairs
values=key.values()
ifvalues:
returnvalues
return (key,)
# Iterable but not text or mapping => list- or tuple-like
elifisinstance(key, Iterable) andnot (isinstance(key, str) orisinstance(key, bytes)):
returnkey
# Scalar value, wrap in tuple.
else:
return (key,)

Which is unfortunate, since the underlying verify method expects a Key object with the alg specified:

python-jose/jose/jws.py

Lines 207 to 208 in be8e914

ifnotisinstance(key, Key):
key=jwk.construct(key, alg)

Consequently, it's possible to use a set of keys with mismatching algorithms (i.e. in frameworks that consume this library), which would in turn make those libraries susceptible to algorithm confusion (see also: the HS256/RS256 attack from a few years ago).

This is identical to the problem in googleapis/php-jwt#351https://seclists.org/fulldisclosure/2021/Aug/14

Note: This particular sharp edge isn't covered by the JWT Best Practices RFC.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions