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

> Explore libssh2-publickey-list-calc-poc vulnerabilities. This proof-of-concept reveals arbitrary code execution flaws in the public-key subsystem, enabling attacker-controlled process spawning.

- Repository: [bikini/exploitarium](https://github.com/bikini/exploitarium)
- Tags: deep-dive
- Published: 2026-09-06

---

**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`](https://github.com/bikini/exploitarium/blob/main/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`](https://github.com/bikini/exploitarium/blob/main/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`](https://github.com/bikini/exploitarium/blob/main/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:

```bash
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`](https://github.com/bikini/exploitarium/blob/main/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:

```bash
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`](https://github.com/bikini/exploitarium/blob/main/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

```bash
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:

```bash
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`](https://github.com/bikini/exploitarium/blob/main/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`](https://github.com/bikini/exploitarium/blob/main/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`](https://github.com/bikini/exploitarium/blob/main/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`](https://github.com/bikini/exploitarium/blob/main/poc/live_publickey_server.py) (a Python-based malicious SSH server) and [`poc/live_publickey_client_win64.c`](https://github.com/bikini/exploitarium/blob/main/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`](https://github.com/bikini/exploitarium/blob/main/src/publickey.c) and prevent both the allocation-wrap and stale-callback attack vectors.