
Exploit de prueba de concepto para CVE-2026-14669, un desbordamiento de búfer en el montón de la abreviatura de zona horaria de to_char() de PostgreSQL que permite RCE mediante fuga de información y cadena ROP; incluye laboratorio Docker y PoC automatizado.
La función to_char() de PostgreSQL presenta una vulnerabilidad de desbordamiento de búfer en el montón al procesar el formato de zona horaria. Un atacante puede provocar una escritura fuera de los límites en un búfer fijo de 25 bytes configurando una abreviatura de zona horaria POSIX extremadamente larga, logrando ejecución remota de código mediante fuga de información y una cadena ROP.
to_char(timestamptz) de PostgreSQL| Serie de PostgreSQL | Rango afectado |
|---|---|
| 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 |
La ruta de procesamiento DCH_TZ / DCH_tz en formatting.c utiliza un búfer de pila fijo de 25 bytes para almacenar la abreviatura de la zona horaria, pero no hay ninguna comprobación de la longitud de entrada. Cuando la abreviatura de la zona horaria supera los 24 bytes, strcpy() escribe fuera de los límites en la memoria del montón.
Ruta de activación:
SET TIME ZONE '<超长缩写>+00';
SELECT to_char(now()::timestamptz, 'TZ');
↓
DCH_to_char() → DCH_from_char_action()
↓
strcpy(buf, tmtcTzn(...)) ← 堆溢出
El PoC de V12 Security consta de tres fases:
Mediante el desbordamiento del montón se corrompen objetos de montón adyacentes, filtrando la dirección base de PIE y punteros de montón para romper ASLR.
Se utiliza un objeto grande o campos bytea para colocar la cadena de gadgets ROP en el montón.
El segundo desbordamiento sobrescribe los punteros de función en el montón y salta a la cadena ROP para ejecutar comandos arbitrarios (con privilegios del usuario postgres).
poc.py - Script de explotación completo (210 líneas, dirigido a PostgreSQL 19beta1)requirements.txt - Dependencias de Python (psycopg, pwntools)docker-compose.yml - Entorno de pruebas de la vulnerabilidaddocker-compose up -d
Espere a que el contenedor termine de iniciarse (pase la comprobación de salud):
docker logs pg-tzlab
pip install -r requirements.txt
python3 poc.py
Se conecta por defecto a 127.0.0.1:55432, con usuario postgres y contraseña postgres.
Tras una explotación exitosa, se puede ver la salida de la ejecución del comando en los registros del contenedor:
docker logs pg-tzlab | grep PWNED
Edite las constantes en poc.py:
HOST, PORT - Dirección de destinoDEFAULT_COMMAND - Comando a ejecutar⚠️ Importante: este PoC tiene codificadas las direcciones de desplazamiento de una compilación específica (imagen Docker postgres:19beta1 sha256:a6bdd01...). En otras versiones es necesario localizar los gadgets nuevamente.
SET TIME ZONE excesivamente largas (más de 50 caracteres)⚠️ Este PoC es solo para investigación de seguridad, verificación de vulnerabilidades y pruebas defensivas.
El uso de este PoC implica que acepta cumplir las leyes y regulaciones locales y los límites de autorización del sistema objetivo.