内容提要
作者在挖掘 pg_clickhouse 漏洞后,追问 PostgreSQL 如何判定数据类型,发现 Datum 本身不含类型信息,类型由 OID 决定。他利用预编译语句:先以 UUID 字段构造复合类型并准备查询,执行前用 ALTER TYPE 将字段改为 bytea,使旧 UUID 字节被当作 varlena 外部指针解析,触发类型混淆并导致段错误。进一步伪造 ExpandedObjectHeader 与方法表,可劫持控制流调用 system();再借数组元素类型混淆泄露内存地址以绕过 ASLR。该漏洞编号为 CVE-2026-6460,已存在 22 年,共报告 21 个变体,影响几乎所有托管 PostgreSQL 平台。
延伸解读
预编译语句与类型变更的时序窗口
文章揭示的核心问题在于:PostgreSQL 的预编译语句在 PREPARE 阶段完成解析和类型绑定,但执行前仍可通过 ALTER TYPE 修改复合类型的属性类型。由于已存储的 Datum 不会随类型变更而转换,执行时输出函数会按新类型解释旧字节,形成类型混淆。这提醒开发者,在长连接或连接池中复用预编译语句时,若同时进行 DDL 变更,需警惕此类时序风险。
从段错误到控制流劫持的关键机制
作者利用 UUID 字节构造伪造的 ExpandedObjectHeader 和方法表,使 byteaout() 在 detoast 过程中调用攻击者指定的函数指针。由于 PostgreSQL 将对象指针同时作为方法查找依据和调用参数,攻击者可将命令字符串置于对象起始处,从而以 system(H) 形式执行任意命令。这表明,即使没有直接的内存写原语,仅靠类型混淆和可控字节也能实现可靠的代码执行。
ASLR 绕过与数组类型混淆的配合
为绕过地址随机化,作者复用同一类型混淆原语:将复合类型中的 UUID 字段改为 bigint[],使 unnest() 按 text 元素提取并返回指针值,而 SQL 层将其当作 bigint 输出,从而泄露内存地址。三个 UUID 拼接可构造 48 字节的数组结构,精确控制元数据与载荷。这一手法说明,类型混淆不仅能导致崩溃,还能被组合成完整的信息泄露链。
影响范围与托管平台的协调披露
文章指出 CVE-2026-6460 是覆盖 21 个变体的伞形修复,影响几乎所有托管 PostgreSQL 平台,包括兼容性 offerings。作者将可复现 PoC 私下分享给多家云厂商,部分厂商在官方补丁前自行实施缓解。这反映出核心数据库漏洞在托管服务场景下的协调复杂性:基础设施可以外包,但安全风险无法外包,用户需关注各平台的实际修复进度。
Q&A
CVE-2026-6460 是什么漏洞?它影响了哪些 PostgreSQL 部署?
CVE-2026-6460 是一个存在于 PostgreSQL 核心中长达 22 年的类型混淆漏洞。攻击者可通过预编译语句和 ALTER TYPE 改变复合类型字段的类型,使旧值被错误解析,进而导致内存破坏甚至远程代码执行。该漏洞影响几乎所有托管 PostgreSQL 平台,包括 AWS Aurora/RDS、Azure PostgreSQL、Google AlloyDB、Supabase、Ubicloud 等,以及提供 PostgreSQL 兼容服务的厂商。
这个 PostgreSQL 类型混淆漏洞的触发原理是什么?
PostgreSQL 的 Datum 本身不包含类型信息,类型由 OID 决定。作者利用预编译语句:先创建一个包含 UUID 字段的复合类型并准备查询,执行前用 ALTER TYPE 将该字段改为 bytea。执行时,PostgreSQL 仍使用旧的 UUID 字节,但 byteaout() 会将其解释为 varlena 外部扩展对象头,从而触发类型混淆并导致段错误。
如何利用这个类型混淆漏洞实现远程代码执行(RCE)?
通过控制 UUID 字节伪造一个 ExpandedObjectHeader 结构及其方法表,将方法表中的函数指针指向 system()。当 PostgreSQL 调用 EOH_get_flat_size 时,会间接调用 system(),并将伪造的对象指针作为参数传入,从而执行任意命令。
在利用过程中如何绕过 ASLR 泄露内存地址?
作者利用相同的类型混淆原语,构造一个包含三个 UUID 字段的复合类型,将第一个字段从 UUID 改为 bigint[]。通过 unnest() 提取数组元素时,PostgreSQL 将 text 指针作为 bigint 返回,从而泄露内存地址。加上偏移量 +4 可跳过头部,得到可控负载的地址。
这个漏洞是如何被发现的?与 pg_clickhouse 漏洞有何关联?
作者在利用 pg_clickhouse 扩展漏洞时,对 PostgreSQL 如何判定数据类型产生疑问,进而深入研究核心机制。在讨论预编译语句时意识到可以在执行前更改类型,最终发现了这个存在 22 年的类型混淆原语。
CVE-2026-6460 的修复涉及哪些内容?报告了多少个变体?
该漏洞作为总括修复(umbrella fix)引入了复合属性版本化,并关联了另外 5 个 CVE(如 CVE-2026-120142、CVE-2026-120148 等),共报告了 21 个变体。修复随 2026 年 11 月 9 日的大型安全更新发布,该更新包含 52 个新 CVE。