
PoC for CVE-2026-2005
针对 PostgreSQL pgcrypto 扩展中 PGP 会话密钥解析的堆缓冲区溢出的 PoC 利用程序,可实现任意内存读写并将权限提升至超级用户。
完整技术细节请参阅 Zeroday Cloud 公告。

从存在漏洞的提交克隆并编译 PostgreSQL,以便二进制文件的符号偏移完全匹配。该利用程序通过将泄露的指针与 ELF 符号偏移进行匹配来解析 ASLR 基址 - 不同的构建或版本将具有不同的偏移量,并会导致失败。
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 消息损坏了 mdst 缓冲区的 malloc 块头部。当 PostgreSQL 对损坏的块调用 pfree() 时,分配器会发出包含指针地址的错误,从而泄露 mdst->data 的堆位置。
任意读取 - 第二次溢出将 mdst->data 覆盖为指向 (leaked_ptr - 0x10000)。解密后,mbuf_steal_data() 返回该地址的内容作为解密输出,从而转储可能包含陈旧代码指针的堆内存。
指针扫描 - 扫描十六进制转储,查找看起来像代码地址(>= 0x500000000000)但不在堆区域中的 8 字节小端值。这些是候选 PIE(位置无关可执行文件)指针。
PIE 基址投票 - 针对 postgres 二进制文件的 ELF 符号偏移测试每个候选地址。对于每个页面偏移匹配的 (addr - sym_offset) 对,投一票。保留获得 10 票以上的候选者;按票数排序的最小基址(PIE 是最低映射的 ELF 段)为最佳候选者。
PIE 基址验证 - 利用程序使用任意读取原语,读取 (candidate_base + current_user_offset) 处的 CurrentUserId,并将其与会话的已知 OID 进行比较。匹配则确认 PIE 基址。
任意写入 - 溢出损坏了 msrc 和 MBuf 头部。伪造的 / 指向一个嵌入的 sym 加密数据包,其中包含加密的超级用户 OID (10)。伪造的 指向 ( 是为了弥补 中 将输出长度写入前 4 个字节)。
pip install -r requirements.txt)pgcrypto 的 PostgreSQL此概念验证仅用于教育和防御性研究目的。仅可在您拥有或已获得明确测试授权的系统上使用。
| 参数 | 默认值 | 描述 |
|---|
--binary | (postgres 二进制文件) | 用于符号提取的 postgres 二进制文件路径 |
--dbname | postgres | 目标数据库名称 |
--host | localhost | PostgreSQL 主机 |
--port | 5432 | PostgreSQL 端口 |
--user | postgres | 数据库用户 |
--password | (空) | 数据库密码 |
--cmd | whoami | 权限提升后执行的 OS 命令 |
--gdb | (标志) | 在溢出点通过 tmux 附加 GDB |
mdstmsrc->dataread_posmdst->dataCurrentUserId - 4-4pgp-pgsql.c:533SET_VARSIZE权限提升 - 当 CurrentUserId 被覆盖为 10(引导超级用户)后,COPY FROM PROGRAM 以 postgres 系统用户身份执行指定的 OS 命令。