|
5 | 5 | import pytest
|
6 | 6 |
|
7 | 7 | from jose import jws, jwt
|
8 |
| -from jose.exceptions import JWTError |
| 8 | +from jose.exceptions import JWTError, JWKError |
9 | 9 |
|
10 | 10 |
|
11 | 11 | @pytest.fixture
|
@@ -522,3 +522,36 @@ def test_require(self, claims, key, claim, value):
|
522 | 522 | new_claims[claim] = value
|
523 | 523 | token = jwt.encode(new_claims, key)
|
524 | 524 | jwt.decode(token, key, options=options, audience=str(value))
|
| 525 | + |
| 526 | + def test_CVE_2024_33663(self): |
| 527 | + """Test based on https://github.com/mpdavis/python-jose/issues/346""" |
| 528 | + from Crypto.PublicKey import ECC |
| 529 | + from Crypto.Hash import HMAC, SHA256 |
| 530 | + |
| 531 | + # ----- SETUP ----- |
| 532 | + # generate an asymmetric ECC keypair |
| 533 | + # !! signing should only be possible with the private key !! |
| 534 | + KEY = ECC.generate(curve='P-256') |
| 535 | + |
| 536 | + # PUBLIC KEY, AVAILABLE TO USER |
| 537 | + # CAN BE RECOVERED THROUGH E.G. PUBKEY RECOVERY WITH TWO SIGNATURES: |
| 538 | + # https://en.wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm#Public_key_recovery |
| 539 | + # https://github.com/FlorianPicca/JWT-Key-Recovery |
| 540 | + PUBKEY = KEY.public_key().export_key(format='OpenSSH').encode() |
| 541 | + |
| 542 | + # ---- CLIENT SIDE ----- |
| 543 | + # without knowing the private key, a valid token can be constructed |
| 544 | + # YIKES!! |
| 545 | + |
| 546 | + b64 = lambda x:base64.urlsafe_b64encode(x).replace(b'=',b'') |
| 547 | + payload = b64(b'{"alg":"HS256"}') + b'.' + b64(b'{"pwned":true}') |
| 548 | + hasher = HMAC.new(PUBKEY, digestmod=SHA256) |
| 549 | + hasher.update(payload) |
| 550 | + evil_token = payload + b'.' + b64(hasher.digest()) |
| 551 | + |
| 552 | + # ---- SERVER SIDE ----- |
| 553 | + # verify and decode the token using the public key, as is custom |
| 554 | + # algorithm field is left unspecified |
| 555 | + # but the library will happily still verify without warning, trusting the user-controlled alg field of the token header |
| 556 | + with pytest.raises(JWKError): |
| 557 | + data = jwt.decode(evil_token, PUBKEY) |
0 commit comments