
Self-contained Docker lab for practicing exploitation of CVE-2026-2005, a heap buffer overflow in PostgreSQL's pgcrypto extension, enabling privilege escalation and container code execution.
A self-contained Docker lab for practicing exploitation of CVE-2026-2005, a heap buffer overflow in PostgreSQL's pgcrypto extension that enables remote code execution without superuser privileges.
Affected versions: PostgreSQL ≤ 17.7 / 16.11 / 15.15 / 14.20 / 18.1
Fixed in: 18.2, 17.8, 16.12, 15.16, 14.21 (released 2026-02-12)
Requirements: Docker, Docker Compose
git clone <this-repo>
cd CVE-2026-2005
docker compose up -d
PostgreSQL will be listening on 127.0.0.1:5433.
You have obtained database credentials from an application config file:
| Parameter | Value |
|---|
| Host | 127.0.0.1 |
| Port | 5433 |
| Database | targetdb |
| Username | pentester |
| Password | pentester123 |
Connect to confirm access:
psql -h 127.0.0.1 -p 5433 -U pentester -d targetdb
The account has CREATE privilege on the public schema. It is not a superuser.
Capture both flags to complete the lab.
Flag 1 — Database privilege escalation
SELECT * FROM flag_db;
-- Only readable after escalating to superuser within the DB session
Flag 2 — Container code execution
/var/lib/postgresql/flag.txt
-- Only readable after executing commands as the postgres OS user inside the container
Scope note:
COPY TO PROGRAMexecutes inside the Docker container, not on the host. The primary real-world impact is full database read access (all tables, all databases). Reaching the Docker host requires a separate container escape technique.
The flaw is in pgp_parse_pubenc_sesskey() inside pgcrypto/pgp-pubenc.c.
When decrypting a public-key encrypted session key packet, the function derives
the session key length as msglen - 3 from an attacker-controlled RSA/ElGamal
payload and copies it into a fixed 32-byte buffer (PGP_MAX_KEY) without
bounds validation. An attacker can write hundreds of bytes beyond the buffer
boundary.
The exploit proceeds in three stages:
dst struct to overwrite CurrentUserId in .data with 10 (BOOTSTRAP_SUPERUSERID)COPY (SELECT '') TO PROGRAM '<cmd>' executes OS commands as the postgres user inside the container. In a real deployment without Docker, this means OS-level access on the database host.Because the ASLR layout is identical across all connections to the same postmaster process, addresses leaked on one connection remain valid on the next.
pgcrypto/pgp-pubenc.cobjdump -t $(which postgres) | grep CurrentUserIddocker compose down -v
This lab is for authorized security research and education only. Run it only on systems you own or have explicit permission to test.