pyjwt icon indicating copy to clipboard operation
pyjwt copied to clipboard

Unable to verify token with alg: 'none'

Open codingchili opened this issue 5 years ago • 6 comments

Attempting to verify a token with the alg header set to 'none' always fails. This is because the implementation of the NoneAlgorithm 'verify' unconditionally returns False.

    def verify(self, msg, key, sig):
        return False

Expected Result

Verifying any token with the alg header set to 'none' should always succeed whenever the token has a valid format.

Actual Result

Verifying the token fails.

Traceback (most recent call last):
  File "C:/Users/chili/PycharmProjects/untitled/jwtmaker.py", line 7, in <module>
    decoded = jwt.decode(encoded, None, algorithms=['none'])
  File "C:\Users\chili\PycharmProjects\untitled\venv\lib\site-packages\jwt\api_jwt.py", line 92, in decode
    jwt, key=key, algorithms=algorithms, options=options, **kwargs
  File "C:\Users\chili\PycharmProjects\untitled\venv\lib\site-packages\jwt\api_jws.py", line 156, in decode
    key, algorithms)
  File "C:\Users\chili\PycharmProjects\untitled\venv\lib\site-packages\jwt\api_jws.py", line 223, in _verify_signature
    raise InvalidSignatureError('Signature verification failed')
jwt.exceptions.InvalidSignatureError: Signature verification failed

Reproduction Steps

import jwt
encoded = jwt.encode({'some': 'payload'}, None, algorithm='none')
decoded = jwt.decode(encoded, None, algorithms=['none'])

System Information

$ python -m jwt.help
{
  "cryptography": {
    "version": "2.6.1"
  },
  "implementation": {
    "name": "CPython",
    "version": "3.6.5"
  },
  "platform": {
    "release": "10",
    "system": "Windows"
  },
  "pyjwt": {
    "version": "1.7.1"
  }
}

codingchili avatar Mar 01 '19 17:03 codingchili

verifying token with 'none' is a security vulnerability https://auth0.com/blog/critical-vulnerabilities-in-json-web-token-libraries/

kevjin avatar Mar 01 '19 21:03 kevjin

Yes agreed, but only if it's allowed by default in the algorithm whitelist. If I explicitly stated that I want to allow 'none' I would also expect it to verify.

We already enforce the secret to be set to None when using this algorithm. Unless we allow None secrets for other algorithms (which also is a security issue) it should be fine. We could also block mixing 'none' with anything else in the white list.

It seems completely useless even for testing if it doesn't verify. I know 'none' is required by the spec, but is it in line with the spec to always fail verification?

I was using this library to 'forge' an unsigned token for the juice box labs. Got surprised when it didn't work with the sample code when I changed algorithm. Almost changed library right there :)

There's no safeguard against whitelisting both hmac and RSA, should we add one? It's a less obvious security issue.

codingchili avatar Mar 02 '19 07:03 codingchili

Edit api_jws.py and comment out lines 223 and 224.

223 # if not alg_obj.verify(signing_input, key, signature): 224 # raise InvalidSignatureError('Signature verification failed')

Also edit algorithms.py and on line 142 change to 142 invalid_strings = [ ]

These allow you yo use None as an algorithm and use asymmetric keys as HMAC secret. Useful in a test lab environment, obviously do not do this in production.

adriendb avatar Jun 22 '20 16:06 adriendb

I guess, the best solution would be to add two changes:

  1. Add an option with a long name to allow none handling (similar to how --no-preserve-root prevents users from running rm -rf / by accident)
  2. Add specific error for running none if the signature is correct (empty) and option for trusting none is not set. It must be different from default incorrect signature error, as the signature is correct, it is just unsafe.

This way, the algorithm will comply with RFC.

vladko312 avatar Jul 05 '21 20:07 vladko312

This issue is stale because it has been open 60 days with no activity. Remove stale label or comment or this will be closed in 7 days

github-actions[bot] avatar Jun 14 '22 02:06 github-actions[bot]

Actually, RFC considers the need to specifically add none algorithm to whitelist as a good enough measure against accidental usage, but adding a separate option will make it safer.

vladko312 avatar Jun 15 '22 06:06 vladko312

This issue is stale because it has been open 60 days with no activity. Remove stale label or comment or this will be closed in 7 days

github-actions[bot] avatar Aug 15 '22 02:08 github-actions[bot]