PgBouncer SASL Length Field Integer Overflow Crash — CVE-2026-6664
by nicolasjulian (repo notes PoC assistance from an AI model) · 2026-07-05
- Severity
- High
- CVE
- CVE-2026-6664
- Category
- network
- Affected product
- PgBouncer (PostgreSQL connection pooler)
- Affected versions
- <= 1.25.1 (fixed in 1.25.2, commit ddc63c2175825bca9ef3c0a528280acaad76dbaa)
- Disclosed
- 2026-07-05
- Patch status
- patched
Archive entry
intelseclab/poc-archiveMetadata
| Field | Value |
|---|---|
| Date Added | 2026-07-05 |
| Last Updated | 2026-05 |
| Author / Researcher | nicolasjulian (repo notes PoC assistance from an AI model) |
| CVE / Advisory | CVE-2026-6664 |
| Category | network |
| Severity | High |
| CVSS Score | Not specified in source |
| Status | PoC |
| Tags | pgbouncer, postgresql, integer-overflow, sasl, scram, dos, cwe-190 |
| Related | N/A |
Affected Target
| Field | Value |
|---|---|
| Software / System | PgBouncer (PostgreSQL connection pooler) |
| Versions Affected | <= 1.25.1 (fixed in 1.25.2, commit ddc63c2175825bca9ef3c0a528280acaad76dbaa) |
| Language / Platform | C (PgBouncer server), PoC written in Python 3 using raw sockets |
| Authentication Required | No — the bug triggers during the SASL/SCRAM authentication handshake itself, before authentication completes |
| Network Access Required | Yes |
Summary
PgBouncer’s mbuf_get_bytes() bounds check (lib/usual/mbuf.h) computes buf->read_pos + len > buf->write_pos using 32-bit unsigned arithmetic, which wraps around when a client supplies a very large length value in a SASLInitialResponse (‘p’) message, silently bypassing the bounds check. A second integer overflow then occurs in scram_client_first(), where malloc(datalen + 1) wraps 0xFFFFFFFF + 1 to 0, producing a small but non-NULL allocation, followed by a memcpy that attempts to copy the full (attacker-declared) 4GB length from a tiny actual buffer, crashing the process with SIGSEGV. The included PoC connects to a SCRAM-SHA-256-configured PgBouncer instance and sends a crafted SASL initial response with a length field of 0xFFFFFFFF to trigger the crash, causing denial of service against the connection pooler.
Vulnerability Details
Root Cause
In lib/usual/mbuf.h, the vulnerable bounds check reads if (buf->read_pos + len > buf->write_pos). Because read_pos, write_pos, and len are all unsigned 32-bit integers, read_pos + len can wrap around modulo 2^32, making an out-of-range len appear in-range (e.g. 18 + 0xFFFFFFFF mod 2^32 = 17, which is not greater than a small write_pos, so the check passes incorrectly). The fix rewrites this as subtraction (if (len > buf->write_pos - buf->read_pos)), which does not have this overflow behavior. A second, related overflow occurs downstream in scram_client_first() at client.c:1112-1115, where malloc(datalen + 1) with datalen = 0xFFFFFFFF wraps to malloc(0), yielding a small non-NULL allocation that is then passed to memcpy(ibuf, data, datalen) — attempting to copy 4GB from a buffer that is only a few bytes long, crashing the process.
Attack Vector
- Connect to the PgBouncer listener and send a standard PostgreSQL startup message specifying a user and database.
- Initiate SASL/SCRAM-SHA-256 authentication and send a SASLInitialResponse (‘p’) message where the mechanism name is
SCRAM-SHA-256\0and the declared response length field is set to0xFFFFFFFF. - PgBouncer’s
mbuf_get_string/mbuf_get_uint32be/mbuf_get_bytesparsing chain advancesread_posand, due to the 32-bit wraparound in the bounds check, accepts the oversized length as valid. scram_client_first()is invoked with the attacker-controlled0xFFFFFFFFlength, causingmalloc(datalen + 1)to wrap to a 0-byte allocation and the subsequentmemcpyto read far beyond the actual packet buffer, crashing the PgBouncer process (SIGSEGV, exit 139).- The included
poc.pyautomates connecting, sending the startup message and crafted SASL initial response, and detects the crash via a reset/closed connection.
Impact
An unauthenticated network attacker able to reach the PgBouncer listener can remotely crash the PgBouncer process, causing a denial of service for all clients relying on that connection pooler to reach the backend PostgreSQL database.
Environment / Lab Setup
Target: PgBouncer 1.25.1 built from source (pgbouncer/Dockerfile) with SCRAM-SHA-256 auth (pgbouncer.ini), backed by PostgreSQL 16 (postgres/init.sql), orchestrated via docker-compose.yml
Attacker: Python 3, standard library only (socket, struct) — poc.py requires no extra dependencies
Proof of Concept
PoC Script
See
poc.pyin this folder (lab setup:docker-compose.yml,pgbouncer/Dockerfile,pgbouncer/pgbouncer.ini,pgbouncer/gen_userlist.py,postgres/init.sql).
| |
The script connects to PgBouncer as testuser/testdb, performs the PostgreSQL startup handshake, then sends a crafted SASLInitialResponse with a 0xFFFFFFFF length field to trigger the double integer overflow. It reports whether the connection was reset or PgBouncer became unreachable, confirming the crash.
Detection & Indicators of Compromise
Example indicator: PgBouncer process terminates unexpectedly (SIGSEGV / exit 139) immediately
following an incoming SASLInitialResponse ('p' message) during the authentication phase,
before any successful login.
Signs of compromise:
- PgBouncer crash logs or core dumps correlating with incoming connections that never complete authentication.
- Sudden, repeated PgBouncer process restarts/unavailability without corresponding legitimate client authentication failures.
- Network captures showing a SASLInitialResponse message with an anomalously large declared length field (e.g.
0xFFFFFFFF).
Remediation
| Action | Detail |
|---|---|
| Primary fix | Upgrade to PgBouncer 1.25.2 or later, which fixes the mbuf_get_bytes() bounds check (commit ddc63c2175825bca9ef3c0a528280acaad76dbaa) to use subtraction instead of addition, preventing the integer overflow. |
| Interim mitigation | Restrict network access to the PgBouncer listener to trusted clients only, and monitor for repeated PgBouncer process crashes/restarts as an indicator of active exploitation attempts. |
References
Notes
Mirrored from https://github.com/nicolasjulian/bouncer-overflow on 2026-07-05. Source repository README notes this PoC’s description was written with AI assistance but the exploit code is functional.
| |