Skip to content

Malformed JWTs due to different signing algorithms in headers and algorithm parameters #659

@ashutosh1206

Description

@ashutosh1206

Generating JWTs (encode()) with alg key set in headers parameter along with a different algorithm parameter value results in malformed JWTs.

Example headers and algorithm values that will result in malformed tokens:

headers = {"typ": "JWT", "alg": "none"}
algorithm = "HS256"

Expected Result

A token signed with let's say HS256 algorithm should always contain alg value set as HS256 in the JWT header.

Actual Result

Tokens can be signed using an algorithm x (eg. HS256) with token header containing a different alg value

Reproduction Steps

import jwt
payload = {"test": "payload"}
headers = {"typ": "JWT", "alg": "none"}
print(jwt.encode(payload = payload, key = "secret", algorithm = "HS256", headers = headers))

Running the snippet above will give: eyJ0eXAiOiJKV1QiLCJhbGciOiJub25lIn0.eyJ0ZXN0IjoicGF5bG9hZCJ9.PySJLJ2Js8Z1K0acpZrgOhzHp0sea_N5rrNX1L_FJis. Header + payload in this case is signed using HS256, but the header value in the token is: {"typ":"JWT","alg":"none"}

Similarly,

import jwt
payload = {"test": "payload"}
headers = {"typ": "JWT", "alg": "RS256"}
jwt.encode(payload = payload, key = "secret", algorithm = "HS256", headers = headers)

will result in a token signed using HS256, with the token header being {"typ":"JWT","alg":"RS256"}

System Information

$ python -m jwt.help
{
  "cryptography": {
    "version": "3.4.7"
  },
  "implementation": {
    "name": "CPython",
    "version": "3.8.8"
  },
  "platform": {
    "release": "5.8.0-53-generic",
    "system": "Linux"
  },
  "pyjwt": {
    "version": "2.1.0"
  }
}

Root cause

algorithm (L#109 api_jws.py) variable is being used for signing, but header dict (L#93 api_jws.py) is being overwritten with headers method parameter in L#97 api_jws.py leading to alg value being overwritten to the value present in the method parameter headers.

I tried coming up with ways in which this bug could be abused by an adversary, but couldn't find any. And so, I don't think this qualifies as a security issue.

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