
Эксплойт proof-of-concept для CVE-2026-6471, демонстрирующий повышение привилегий в PostgreSQL через логическое декодирование dlopen для достижения произвольного выполнения кода и бэкдора суперпользователя.
Логическое декодирование PostgreSQL позволяет роли, не являющейся суперпользователем, но обладающей привилегией
REPLICATION, создавать слот логической репликации и выбирать
выходной плагин. На затронутых версиях отсутствует проверка авторизации при таком
выборе, поэтому сервер вызывает dlopen() для того, на что указывает имя плагина. Указание
пути к библиотеке запускает код этой библиотеки внутри бэкенда postgres от имени
учётной записи операционной системы, под которой работает сервер. Это выполнение произвольного кода
от имени пользователя ОС сервера базы данных, что для базы данных, хранящей
данные приложения, фактически означает захват сервера.
Исправлено в PostgreSQL 18.6, 17.11, 16.15, 15.19 и 14.24 с помощью
списка разрешённых output_plugin_libraries (по умолчанию pgoutput, test_decoding).
Всё, что не входит в этот список, теперь завершается ошибкой library "X" may not be used as an output plugin до любого вызова dlopen.
Выполните одни и те же шаги против обеих сборок — меняется только версия PostgreSQL. Учётная запись с низкими привилегиями (LOGIN + REPLICATION, не суперпользователь, без доступа к ОС) делает то же, что и обычный подписчик логического декодирования, а затем просит сервер загрузить произвольную библиотеку в качестве выходного плагина. На уязвимой сборке эта библиотека выполняется от имени пользователя ОС postgres и внедряет постоянную роль-бэкдор суперпользователя, так что учётная запись только с репликацией завершает запуск с работающим входом суперпользователя.
cve-2026-6471-postgres-logical-decoding-dlopen.txt — это решение Exploitmatic
(.txt): данные плюс проверки, без кода. Среда выполнения воспроизводит его на
машине. Решение доставляет pwn.so во время выполнения (base64 в файле),
выполняет SQL от имени роли репликации с низкими привилегиями, а затем входит как
роль-бэкдор суперпользователя, которую внедрила полезная нагрузка.pwn.c — исходный код библиотеки полезной нагрузки, а pwn.so — её сборка: один ELF-
конструктор, который выполняется от имени пользователя ОС postgres, подключается через
локальный сокет как суперпользователь базы данных (peer/trust) и создаёт постоянную
роль cve6471_backdoor LOGIN SUPERUSER PASSWORD 'BackdoorPass1'. Она выполняется
только если сервер действительно загружает библиотеку, т.е. только на уязвимой
сборке. Сборка: gcc -Os -shared -fPIC -o pwn.so pwn.c на Linux libc,
соответствующей образу сервера.Предварительные условия: у вас есть доступ к docker.
Папка lab/ содержит точную копию, использованную для проверки этого PoC. Соберите и
запустите две машины (уязвимая = postgres 16.14, исправленная = postgres 16.15):
docker build -t pg-6471-vuln -f lab/Dockerfile.vuln lab
docker build -t pg-6471-fixed -f lab/Dockerfile.fixed lab
docker run -d --name pg-6471-vuln -p 15432:5432 -e POSTGRES_PASSWORD=lab-super-pw pg-6471-vuln
docker run -d --name pg-6471-fixed -p 15433:5432 -e POSTGRES_PASSWORD=lab-super-pw pg-6471-fixed
Обе машины запускают стандартный официальный образ postgres с wal_level=logical.
Скрипт инициализации lab/01-repro.sh создаёт роль с низкими привилегиями, которую использует
решение, repro_rep LOGIN REPLICATION PASSWORD 'repropass', не являющуюся
суперпользователем.
Затем воспроизведите решение:
exploitmatic run cve-2026-6471-postgres-logical-decoding-dlopen.txt 127.0.0.1
Укажите исправленную машину с переопределением переменной, без правки файла:
exploitmatic run cve-2026-6471-postgres-logical-decoding-dlopen.txt 127.0.0.1 \
--var ctr=pg-6471-fixed
ctr — это docker-контейнер, pw — пароль роли репликации.
| цель | результат |
|---|---|
| postgres 16.14 (уязвимая), wal_level=logical | 4/4 подтверждено, вход через бэкдор суперпользователя работает |
| postgres 16.15 (исправленная), wal_level=logical | 3/4 не подтверждено, бэкдора нет |
Только для авторизованного тестирования и исследований, на системах, которыми вы владеете или на тестирование которых имеете разрешение. Этот PoC демонстрирует повышение привилегий после аутентификации: он требует существующей учётной записи базы данных с низкими привилегиями и атрибутом REPLICATION, а также способа разместить управляемый атакующим код там, где пользователь ОС postgres может его загрузить. Это не удалённая атака без аутентификации. Загруженный код достигает суперпользователя базы данных, потому что учётная запись ОС, владеющая сервером, может подключиться через локальный сокет как суперпользователь (peer/trust), что является стандартной практикой развёртывания PostgreSQL.
| шаг | уязвимая 16.14 | исправленная 16.15 |
|---|
| разведка (роль — репликация, не суперпользователь) | проходит | проходит |
| базовый (логический слот со встроенным pgoutput) | проходит | проходит |
| триггер (плагин слота = путь к библиотеке атакующего) | сервер загружает её | отклонено до загрузки |
| захват (вход как внедрённый бэкдор суперпользователя) | суперпользователь | такой роли нет |