
Proof-of-concept exploit for CVE-2026-14669, a PostgreSQL to_char() timezone abbreviation heap buffer overflow enabling RCE through information leak and ROP chain; includes Docker lab and automated PoC.
PostgreSQL to_char() function has a heap buffer overflow vulnerability when handling timezone formatting. By setting an overly long POSIX timezone abbreviation, an attacker can trigger an out-of-bounds write to a fixed 25-byte buffer, and combine it with information leakage and an ROP chain to achieve remote code execution.
to_char(timestamptz) function| PostgreSQL Series | Affected Range |
|---|---|
| 18.x | 18.0 – 18.5 |
| 17.x | 17.0 – 17.10 |
| 16.x | 16.0 – 16.14 |
| 15.x | 15.0 – 15.18 |
| 14.x | 14.0 – 14.23 |
The DCH_TZ / DCH_tz handling path in formatting.c uses a 25-byte fixed stack buffer to store the timezone abbreviation, but there is no check on input length. When the timezone abbreviation exceeds 24 bytes, strcpy() writes out of bounds into heap memory.
Trigger path:
SET TIME ZONE '<超长缩写>+00';
SELECT to_char(now()::timestamptz, 'TZ');
↓
DCH_to_char() → DCH_from_char_action()
↓
strcpy(buf, tmtcTzn(...)) ← 堆溢出
V12 Security's PoC consists of three phases:
Use the heap overflow to corrupt adjacent heap objects and leak the PIE base and heap pointers to defeat ASLR.
Use large objects or bytea fields to lay out the ROP gadget chain on the heap.
The second overflow overwrites a function pointer on the heap, jumping to the ROP chain to execute arbitrary commands (as the postgres user).
poc.py - Full exploit script (210 lines, targeting PostgreSQL 19beta1)requirements.txt - Python dependencies (psycopg, pwntools)docker-compose.yml - Vulnerability test environmentdocker-compose up -d
Wait for the container to finish starting (health check passed):
docker logs pg-tzlab
pip install -r requirements.txt
python3 poc.py
By default it connects to 127.0.0.1:55432 with username postgres and password postgres.
After successful exploitation, you can see the command execution output in the container logs:
docker logs pg-tzlab | grep PWNED
Edit the constants in poc.py:
HOST, PORT - target addressDEFAULT_COMMAND - command to execute⚠️ Important: This PoC hardcodes the offsets of a specific build (postgres:19beta1 Docker image sha256:a6bdd01...). Other versions will require relocating gadgets.
SET TIME ZONE statements (> 50 characters)⚠️ This PoC is for security research, vulnerability validation, and defensive testing only.
By using this PoC, you agree to comply with local laws and regulations and the authorization boundaries of the target system.