libssh2-publickey-list-calc-poc: Critical Vulnerabilities in the libssh2 Public Key Subsystem

The libssh2-publickey-list-calc-poc demonstrates arbitrary code execution vulnerabilities in libssh2's public-key subsystem, specifically an integer overflow allocation-wrap on Win32 and a stale-callback use-after-free on Win64, both exploitable through the libssh2_publickey_list_fetch() function to spawn attacker-controlled processes like calc.exe.

The bikini/exploitarium repository hosts the libssh2-publickey-list-calc-poc, a collection of proof-of-concept exploits targeting the SSH public-key list parser in libssh2. These vulnerabilities allow remote attackers to achieve arbitrary code execution by manipulating how the library processes malformed public-key responses during the list fetching operation.

Win32 Allocation-Wrap Integer Overflow

On 32-bit Windows architectures, the vulnerability stems from an integer overflow in the buffer size calculation within libssh2_publickey_list_fetch(). The function computes the allocation size using num_attrs * sizeof(libssh2_publickey_attribute), where both operands are 32-bit values.

Heap Corruption via Integer Overflow

When num_attrs is sufficiently large, this multiplication wraps around to a small value—specifically 4 bytes—causing the allocator to create a tiny buffer. The parser then writes attacker-controlled attrs fields past this boundary, corrupting adjacent heap memory. The PoC file poc/publickey_win32_heap_groom_calc_repro.c (lines 95-115) demonstrates grooming the heap to position a victim structure immediately after the under-allocated buffer. By overwriting the victim's callback pointer and triggering its invocation, the exploit launches calc.exe.

Win64 Stale-Callback Use-After-Free

On 64-bit Windows, the vulnerability manifests as a use-after-free condition during list growth operations. Rather than relying on integer overflow, this attack exploits the lifetime management of public-key list entries.

Arbitrary Free and Callback Forgery

The exploit implemented in poc/publickey_win64_arbitrary_free_calc_repro.c (lines 27-31) transmits a crafted "version" response that frees a victim object. A subsequent malformed "publickey" response forces the list to grow, allocating the new entry into the same heap slot previously occupied by the freed victim. During cleanup, the library blindly frees the attacker-controlled attrs pointers stored in this entry, effectively restoring the victim object with forged callback fields. When the overwritten callback is invoked, it executes arbitrary code—demonstrated by spawning calc.exe.

Live Transport Exploitation

The repository provides a complete client-server implementation for demonstrating these vulnerabilities over actual SSH transports. This validates that the vulnerabilities are reachable through network protocols, not just theoretical parsing errors.

Malicious SSH Server Setup

The Python server poc/live_publickey_server.py orchestrates the attack by listening on port 2228 and transmitting groomed version packets followed by malformed publickey responses. The server accepts parameters to control the victim address and heap offset:

python3 poc/live_publickey_server.py --host 127.0.0.1 --port 2228 \
    --victim 0x0000013370000000 --offset 27

Windows Client Execution

The companion client poc/live_publickey_client_win64.c connects to the malicious server and processes the crafted responses. When compiled against vulnerable libssh2 objects, the client triggers the stale-callback free chain:

wine ./live_publickey_client_win64.exe 127.0.0.1 2228 calc

If the underlying libssh2 build is vulnerable, this command launches calc.exe on the Windows host.

Mitigations and Checked Builds

The PoC repository includes "checked" builds of libssh2 that implement specific hardening measures to prevent exploitation. These mitigations are implemented in src/publickey.c and demonstrate how to close the attack surface.

Integer Overflow Validation

Checked builds validate that num_attrs values would not overflow the multiplication num_attrs * sizeof(libssh2_publickey_attribute). Rejecting malicious values prevents the allocation-wrap condition on Win32.

Zero-Initialization of List Entries

To prevent the use-after-free condition on Win64, checked builds zero-initialize newly-grown list entries immediately after allocation. This ensures that stale pointers cannot persist across free and reallocation cycles, neutralizing the callback forgery technique.

Building the Proof-of-Concept

You can compile the Win64 exploit against both vulnerable and patched libssh2 objects to observe the mitigation effectiveness.

Compiling Against Vulnerable Objects

x86_64-w64-mingw32-gcc -O2 -s -DLIBSSH2_WINCNG \
    -I"$LIBSSH2_SRC/src" -I"$LIBSSH2_SRC/include" \
    -o build/publickey_win64_arbitrary_free_calc_repro.exe \
    poc/publickey_win64_arbitrary_free_calc_repro.c \
    "$LIBSSH2_OBJDIR/publickey_win64.o" -lws2_32 -lbcrypt

Compiling Against Checked (Mitigated) Objects

Replacing the object file with the checked version prevents calc.exe from launching, confirming the fix:

x86_64-w64-mingw32-gcc -O2 -s -DLIBSSH2_WINCNG \
    -I"$LIBSSH2_SRC/src" -I"$LIBSSH2_SRC/include" \
    -o build/publickey_win64_arbitrary_free_calc_repro_checked.exe \
    poc/publickey_win64_arbitrary_free_calc_repro.c \
    "$LIBSSH2_OBJDIR/publickey_win64_checked.o" -lws2_32 -lbcrypt

Summary

  • The Win32 exploit in poc/publickey_win32_heap_groom_calc_repro.c leverages an integer overflow when calculating num_attrs * sizeof(libssh2_publickey_attribute) to achieve heap corruption and callback overwrite.
  • The Win64 exploit in poc/publickey_win64_arbitrary_free_calc_repro.c exploits a use-after-free during list growth to forge callback pointers and execute arbitrary code.
  • Both vulnerabilities reside in the libssh2_publickey_list_fetch() function within src/publickey.c.
  • Mitigations include validating num_attrs for overflow conditions and zero-initializing new list entries to prevent stale pointer exploitation.

Frequently Asked Questions

What is the libssh2-publickey-list-calc-poc?

The libssh2-publickey-list-calc-poc is a proof-of-concept exploit suite housed in bikini/exploitarium that demonstrates critical vulnerabilities in libssh2's public-key list parsing functionality. It targets the libssh2_publickey_list_fetch() function to achieve arbitrary code execution on both 32-bit and 64-bit Windows systems.

How does the Win32 integer overflow lead to code execution?

On Win32, the calculation num_attrs * sizeof(libssh2_publickey_attribute) overflows to 4 bytes, causing a buffer under-allocation. The parser writes attacker-controlled data beyond this buffer, overwriting adjacent heap structures containing function pointers. By controlling the overwrite data, attackers redirect execution to launch processes like calc.exe.

What files are involved in the live transport demonstration?

The live transport proof uses poc/live_publickey_server.py (a Python-based malicious SSH server) and poc/live_publickey_client_win64.c (a Windows client binary). Together, they demonstrate that the vulnerabilities are exploitable over actual network connections rather than just in isolated parsing tests.

How do the checked builds prevent exploitation?

Checked builds implement two key mitigations: they reject num_attrs values that would trigger integer overflow during size calculation, and they zero-initialize newly allocated list entries to prevent use-after-free conditions. These changes are implemented in src/publickey.c and prevent both the allocation-wrap and stale-callback attack vectors.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →