Durante 12 años, una cuenta de respaldo funcionó como puerta trasera desde PostgreSQL hacia el sistema operativo

Durante 12 años, una cuenta de respaldo funcionó como puerta trasera desde PostgreSQL hacia el sistema operativo

Un único privilegio de servicio permitía subir código arbitrario y convertir el acceso a replicación en la toma de control del servidor.

image

Una cuenta de servicio habitual para la replicación de PostgreSQL durante más de diez años pudo convertirse en una puerta trasera desde la base de datos directamente al sistema operativo del servidor. La vulnerabilidad apareció en PostgreSQL 9.4 en 2014 y permitía a una cuenta con el permiso REPLICATION ejecutar código nativo arbitrario.

El problema recibió el identificador CVE-2026-6471 y una puntuación de 7,2 según CVSS. El equipo de Cyera llamó a la técnica PostGREShell. Para el ataque, el atacante necesitaba credenciales de un usuario con el atributo REPLICATION y la decodificación lógica activada. Ese tipo de cuentas usan sistemas de copia de seguridad, servidores de respaldo, canalizaciones CDC y otras herramientas que necesitan leer el registro de cambios de PostgreSQL.

La raíz del problema estaba en el mecanismo de carga de complementos de decodificación lógica. Un cliente con permiso REPLICATION puede crear un slot de replicación y especificar un complemento que convierte las entradas WAL en un flujo de cambios. PostgreSQL pasaba el nombre indicado directamente al cargador de bibliotecas del sistema, sin aplicar la verificación de ruta que protege el comando SQL LOAD habitual.

Como resultado, en lugar del complemento de confianza se podía especificar cualquier biblioteca accesible para el usuario del sistema PostgreSQL. En Linux y macOS el servidor cargaba el archivo mediante dlopen(), y en Windows usaba LoadLibrary(). En Windows el ataque podía realizarse de forma completamente remota: una ruta UNC podía provocar que el servidor obtuviera una DLL maliciosa desde un recurso SMB externo. En algunas configuraciones de Linux y macOS un escenario similar es posible a través de NFS, y en los demás casos el atacante primero debía colocar la biblioteca en el servidor por otro medio.

Tras la carga, la biblioteca se ejecutaba dentro del proceso de PostgreSQL con los privilegios del usuario del sistema bajo el que se ejecuta la base de datos. Los especialistas de Cyera demostraron que ese código podía eludir el modelo de control de acceso SQL, modificar el catálogo del sistema pg_authid y convertir la cuenta de servicio original en superusuario. A partir de ahí el atacante obtiene acceso a todas las bases, puede leer los archivos accesibles para el servidor, ejecutar comandos del sistema operativo y persistir en el sistema.

Cyera también encontró en VirusTotal 114 complementos maliciosos de PostgreSQL, incluidos mineros, troyanos y shells inversos. El hallazgo no demuestra la explotación específicamente de CVE-2026-6471 en ataques reales. Los investigadores no reportaron casos confirmados de uso de PostGREShell contra organizaciones al momento de la divulgación.

Los desarrolladores de PostgreSQL cerraron la vulnerabilidad el 13 de agosto en las versiones 18.6, 17.11, 16.15, 15.19 y 14.24. En la actualización apareció el parámetro output_plugin_libraries, que permite usar solo complementos de decodificación lógica explícitamente confiables. Por defecto la lista contiene los integrados pgoutput y test_decoding, por lo que a los administradores que usan wal2json, decoderbufs u otros complementos externos les toca añadir manualmente las bibliotecas confiables en la configuración tras actualizar.

El camino vulnerable existía desde la introducción de la decodificación lógica en PostgreSQL 9.4. En el análisis de PostGREShell el equipo de Cyera recomienda no limitarse a actualizar: revisar todas las cuentas con REPLICATION, eliminar privilegios innecesarios, restringir las direcciones permitidas en pg_hba.conf y cerrar las conexiones salientes a SMB y NFS donde no sean necesarias. Las correcciones oficiales se publicaron para las ramas compatibles de PostgreSQL 14–18, por lo que las versiones antiguas 9.4–13 requieren migrar a una rama actual.