
PoC for CVE-2026-2005
Эксплойт PoC для переполнения буфера в куче при парсинге ключа сессии PGP в расширении pgcrypto PostgreSQL, приводящий к произвольному чтению/записи памяти и повышению привилегий до суперпользователя.
Полные технические детали см. в рекомендации Zeroday Cloud.

Клонируйте и скомпилируйте PostgreSQL из уязвимого коммита, чтобы смещения символов бинарного файла совпадали точно. Эксплойт определяет базу ASLR путем сопоставления утекших указателей со смещениями символов ELF — разные сборки или версии будут иметь разные смещения и не сработают.
git clone https://github.com/postgres/postgres.git
cd postgres
git checkout 4b324845ba5d24682b9b3708a769f00d160afbd7
./configure \
--prefix="$HOME/projects/pg/pgsql" \
--with-libxml \
--with-libxslt \
--enable-debug \
--with-ssl=openssl
make -j$(nproc)
make install-world-bin
pip install -r requirements.txt
python poc.py \
--binary "$HOME/projects/pg/pgsql/bin/postgres" \
--dbname test-db \
--host 127.0.0.1 \
--port 5432 \
--user test-user \
--password secret \
--cmd id
Эксплойт проходит 7 этапов:
Утечка указателя кучи — специально созданное PGP-сообщение повреждает заголовок блока malloc буфера mdst. Когда PostgreSQL вызывает pfree() на поврежденном блоке, аллокатор выдает ошибку, содержащую адрес указателя, раскрывая расположение в куче mdst->data.
Произвольное чтение — второе переполнение перезаписывает mdst->data для указания на (leaked_ptr - 0x10000). После дешифрования mbuf_steal_data() возвращает содержимое по этому адресу как расшифрованный вывод, дампя память кучи, которая может содержать устаревшие указатели кода.
Сканирование указателей — шестнадцатеричный дамп сканируется на 8-байтовые значения с прямым порядком байтов, похожие на адреса кода (>= 0x500000000000), но не находящиеся в области кучи. Это кандидаты указателей PIE (Position Independent Executable).
Голосование за базу PIE — каждый адрес-кандидат проверяется на смещения символов ELF из бинарного файла postgres. Для каждой пары (addr - sym_offset), где смещение страницы совпадает, отдается голос. Кандидаты с 10+ голосами сохраняются; наименьшая база (PIE — это самый низкий отображаемый сегмент ELF), отсортированная по голосам, является лучшим кандидатом.
Проверка базы PIE — используя примитив произвольного чтения, эксплойт читает CurrentUserId по адресу и сравнивает его с известным OID сессии. Совпадение подтверждает базу PIE.
pip install -r requirements.txt)pgcryptoЭтот Proof of Concept предназначен только для образовательных и защитных исследовательских целей. Используйте только против систем, которыми вы владеете или на тестирование которых имеете явное разрешение.
| Argument | Default | Описание |
|---|
--binary | (postgres binary) | Путь к бинарному файлу postgres для извлечения символов |
--dbname | postgres | Имя целевой базы данных |
--host | localhost | Хост PostgreSQL |
--port | 5432 | Порт PostgreSQL |
--user | postgres | Пользователь базы данных |
--password | (empty) | Пароль базы данных |
--cmd | whoami | Команда ОС для выполнения после повышения привилегий |
--gdb | (flag) | Присоединить GDB через tmux в точке переполнения |
(candidate_base + current_user_offset)Произвольная запись — переполнение повреждает заголовки MBuf как msrc, так и mdst. Поддельные msrc->data/read_pos указывают на встроенный симметрично зашифрованный пакет, содержащий зашифрованный OID суперпользователя (10). Поддельный mdst->data указывает на CurrentUserId - 4 (учитывая, что SET_VARSIZE в pgp-pgsql.c:533 записывает длину вывода в первые 4 байта).
Повышение привилегий — после перезаписи CurrentUserId на 10 (начальный суперпользователь), COPY FROM PROGRAM выполняет указанную команду ОС от имени системного пользователя postgres.