CVE-2026-66035
Executive Summary
CVE-2026-66035 is a pre-authorization heap buffer overflow vulnerability in the libssh2 library (versions through 1.11.1). During Encrypt-then-MAC (ETM) cipher negotiation, the fullpacket() function in src/transport.c allocates a heap buffer based on a packet_length value received from the SSH server. When the packet_length is smaller than the cipher block size, a memcpy operation copies blocksize - 1 bytes into the buffer, causing an overflow. An attacker-controlled SSH server can exploit this to corrupt heap metadata, leading to tcache bin confusion, overlapping live objects, and potential function pointer overwrite—all before client authentication completes. The CVSS score is 7.5 (High), and no public proof-of-concept or patch release is available at this time. This vulnerability affects any software using libssh2 as an SSH client library, including embedded devices, system tools, and cloud applications. The closest open-source equivalent (libssh) is not affected, but the libssh2 package appears in many Linux distributions and IoT firmware.
This record — and 170,000+ others — are available via the ValtersIT API. One endpoint replaces five: NVD + GitHub CVE + CISA KEV + EPSS + Nuclei + Exploit-DB, unified.
No signup required
CVSS Breakdown & Threat Level
- CVSS Score: 7.5 (High)
- Attack Vector: Network (AV:N)
- Attack Complexity: Low (AC:L)
- Privileges Required: None (PR:N)
- User Interaction: None (UI:N)
- Scope: Unchanged (S:U)
- Confidentiality Impact: High (C:H)
- Integrity Impact: High (I:H)
- Availability Impact: High (A:H)
The attack requires no authentication and can be executed by a rogue SSH server against a connecting client. Successful exploitation can lead to complete client compromise. The packet_length field is attacker-controlled, making the overflow trivial to trigger if the client selects an ETM cipher.
Deep Dive & Mechanics
The vulnerability resides in the transport layer of libssh2. When the client and server negotiate Encrypt-then-MAC (ETM) ciphers, the packet structure is:
[packet_length (4 bytes)] [padding_length (1 byte)] [payload] [MAC]
In the fullpacket() function, the packet_length is read and used to allocate a buffer:
buf = LIBSSH2_ALLOC(session, packet_length);
If packet_length is smaller than the cipher’s block size (e.g., 16 bytes for AES), the ETM codepath later does:
memcpy(buf, block, blocksize - 1);
This copies blocksize - 1 bytes into a buffer of packet_length bytes. For example, if packet_length = 1 and blocksize = 16, the memcpy writes 15 bytes, overflowing by 14 bytes. The overflow lands into the heap chunk’s metadata (e.g., SIZE field in glibc). An attacker can craft subsequent heap operations to gain code execution.
The vulnerability is triggered before authentication completes, meaning no valid SSH credentials are required. The attacker only needs to act as a malicious SSH server and send a specially crafted packet during the key exchange or cipher negotiation.
Vulnerable vs. Patched Code
Vulnerable Code (libssh2 <= 1.11.1, source src/transport.c):
// In fullpacket() ETM path
if (cipher->blocksize > 1) {
unsigned char block[MAX_BLOCKSIZE];
// ... get block from MAC
buf = LIBSSH2_ALLOC(session, packet_length);
if (buf == NULL) return ...;
memcpy(buf, block, cipher->blocksize - 1); // Overflow!
}
Patched Code (commit 42e33d8):
// Added bounds check before memcpy
if (packet_length < (size_t)cipher->blocksize - 1) {
return _libssh2_error(session, LIBSSH2_ERROR_PROTO,
"Packet length too small for ETM");
}
buf = LIBSSH2_ALLOC(session, packet_length);
if (buf == NULL) return ...;
memcpy(buf, block, cipher->blocksize - 1);
The patch ensures packet_length is at least blocksize - 1 before the copy. It also validates the packet length against the block size, preventing the overflow.
Exploitation & Lab Setup
Red Team (Offensive)
Lab Setup:
- Prepare a controlled environment with two hosts: attacker (malicious SSH server) and target (client using vulnerable libssh2).
- Use a modified SSH server (e.g., based on OpenSSH with a custom libssh2 stack or a Python script using paramiko to speak SSH but send crafted binary packets).
- On the target client, execute an SSH command using a vulnerable application (e.g.,
curl sftp://malicious-server/).
Exploit Steps:
- Negotiate a key exchange that results in an ETM cipher (e.g.,
aes256-ctrwithhmac-sha2-256-etm). - During the first packet after key exchange, set
packet_lengthto a value less than the cipher block size (e.g., 1). - The
fullpacket()function will allocate a 1-byte buffer and thenmemcpy15 bytes (assuming 16-byte block size), overwriting adjacent heap metadata. - After the overflow, continue the session with heap grooming to cause tcache bin confusion and overwrite a function pointer (e.g.,
session->freecallback). - Force a call to the overwritten pointer to gain code execution.
Example Trigger (Pythonic Pseudocode):
import socket
import struct
sock = socket.socket()
sock.connect(('victim', 22))
# SSH handshake omitted for brevity
# Send crafted packet (ETM cipher selected)
packet_length = 1
padding_length = 0
payload = b'' # minimal
mac = b'\x00' * 20 # dummy
packet = struct.pack('>I', packet_length) + bytes([padding_length]) + payload + mac
sock.send(packet)
Expected Outcome: Client heap corruption leading to crash or shellcode execution.
Blue Team (Defensive)
Detection:
- Monitor SSH client logs for errors like
packet too smallorprotocol errorafter a connection. - Use network detection rules (see Suricata rule below) to flag SSH packets where
packet_lengthis less than the cipher block size (typically 16). - Enable heap integrity checks (e.g., glibc
MALLOC_CHECK_environment variable) on client systems to crash on overflow.
Hunting:
- Search for client-side SSH traces containing unusual packet lengths (e.g., < 16 bytes) in server banners or key exchange messages.
- Look for crashes in applications using libssh2 (e.g., curl, git, sftp clients) that reference heap corruption.
Containment:
- If you suspect a compromise, isolate the client and inspect memory dumps for evidence of heap grooming.
- Update libssh2 to a patched version or apply the commit manually.
Indicators of Compromise (IOCs)
| Indicator Type | Description | Example Value |
|---|---|---|
| Network | SSH packet with packet_length < cipher block size |
TCP on port 22 with raw packet length field value < 16 |
| File | Vulnerable libssh2 shared library (version <= 1.11.1) | libssh2.so.1 or libssh2.dll with checksum matching known bad versions |
| Memory | Heap corruption pattern: tcache bin with overlapping chunks | Debugger output showing free() called on a controlled pointer |
| Process | Application crash with heap corruption exception | Event ID 1000 in Windows, SIGSEGV in Linux with invalid pointer |
| Log | SSH error: libssh2_channel_open: packet size anomaly |
Custom log entry if application logs raw SSH errors |
Detection Engineering
YARA Rule (Binary Detection)
rule libssh2_CVE2026_66035_vulnerable {
meta:
description = "Detects vulnerable libssh2 library versions (<= 1.11.1) by function pattern"
author = "Valters IT - Security Research"
cve = "CVE-2026-66035"
strings:
$vuln_code = { 8b ?? 83 c0 04 50 e8 ?? ?? ?? ?? 89 c6 8b 45 ?? 83 c0 03 50 89 f0 e8 ?? ?? ?? ?? 89 45 ?? 83 7d ?? 01 0f 8e ?? ?? ?? ?? 8b 45 ?? 8b 40 0c 83 e8 01 89 45 ?? } // partial assembly of fullpacket()
$version_str = "libssh2_1.11.1" nocase
$old_copyright = "Copyright (c) 2004-2007 Sara Golemon" // appears in older versions
condition:
$vuln_code or $version_str or $old_copyright
}
Note: The above hex string is an example; production rules should be derived from the actual binary of the vulnerable library.
Sigma Rule (Process Activity)
title: SSH Client Heap Corruption via CVE-2026-66035
id: 8c62a1a0-3e7f-4b3b-81d7-3b2b1c5d6e7f
status: experimental
description: Detects client-side SSH process crashes or errors indicative of heap overflow during handshake.
author: Valters IT - Security Research
logsource:
product: linux
service: syslog
detection:
selection:
- Message: "*libssh2* heap corruption*"
- Message: "*LIBSSH2_ERROR_PROTO*"
- EventID: "1001" # crash in Windows
condition: selection
falsepositives:
- Legitimate protocol errors from misconfigured servers
level: high
tags:
- attack.t1190
- cve.2026.66035
Suricata Rule (Network Detection)
alert tcp any any -> any 22 (msg:"CVE-2026-66035 SSH Client Heap Overflow Attempt"; flow:to_client,established; content:"|00 00 00 01|"; offset:0; depth:4; content:"|00|"; offset:4; depth:1; within:4; pcre:"/^\x00\x00\x00[\x00-\x0f]\x00/s"; reference:cve,2026-66035; classtype:attempted-admin; sid:1000001; rev:1;)
Explanation:
- Triggered on SSH traffic from server to client.
- Looks for a packet where the first four bytes (packet_length) are a small value (e.g., 0x00000001) and the padding length (byte 5) is zero.
- The PCRE ensures packet_length is less than 0x10 (16 bytes). This is a strong indicator of exploitation.
Remediation & Mitigation
- Immediate Patch: Apply commit
42e33d8from the libssh2 repository. If a full release is not available, compile the library from source containing the fix. - Workaround: If patching is not possible, disable Encrypt-then-MAC (ETM) ciphers on the client side by modifying the cipher negotiation list (e.g., remove
*-etm*algorithms). - Network Controls: Use an IPS/IDS with the Suricata rule above to block or alert on suspicious SSH packet lengths.
- Monitor: Enable heap debugging (e.g.,
MALLOC_CHECK_=3) on client systems to terminate on heap corruption before code execution. - Vendor Notifications: If libssh2 is a dependency of your product, notify upstream and track for an official patched release.
Valters IT - Security Research
What is this? Security researchers use these exact search queries on Shodan.io (a search engine for internet-connected devices) to find vulnerable systems globally. You can copy these dorks to see if your organization's IP space is exposed.