PostgreSQL UAF 漏洞深度应急响应:CVE-2026-116304 并行 Worker 匿名 RECORD 类型释放导致的任意代码执行链剖析

深度剖析 PostgreSQL UAF 漏洞 CVE-2026-116304:并行 worker 匿名 RECORD 类型标识符协调缺陷导致共享元组描述符被提前释放,普通数据库用户可借此实现 OS 级任意代码执行。本文从内存生命周期、并行执行器架构、补丁差异到生产环境应急升级与临时缓解策略,给出完整工程落地指南。

🎯 核心技术PostgreSQL 并行执行器 / 共享内存元组描述符
⚡ 架构难度资深架构级 (Level 4)
🚀 核心收益阻断 OS 级 RCE / 30 分钟完成应急闭环

导语:PostgreSQL UAF 漏洞 CVE-2026-116304 是 2026 年度数据库内核层面最值得警惕的内存安全缺陷之一——它把「并行查询」这一性能特性变成了攻击面:普通数据库用户只需构造匿名 RECORD 类型在并行 worker 间的协调场景,即可让一个进程释放共享元组描述符,而另一个进程继续持有并解引用其地址,最终在数据库服务进程的操作系统用户权限下执行任意代码。

作为长期负责数据基础设施的架构师,我对数据库内核 CVE 的判断标准从来不是「CVSS 分数高不高」,而是「攻击前置条件是否廉价」与「爆炸半径是否覆盖宿主机」。CVE-2026-116304 同时踩中两条红线:攻击者只需要一个普通数据库账号(PR:L),无需 UI 交互(UI:N),而后果是 OS 级代码执行(C:H/I:H/A:H)。这意味着一个原本只应读写自己 schema 的业务账号,可能直接跃迁为宿主机上的 postgres 系统用户。本文从内存生命周期、并行执行器架构、补丁差异与生产应急四个维度做完整拆解。

📐 PostgreSQL UAF 漏洞触发链路与并行 Worker 内存生命周期全景
企业级架构规范

flowchart TD
    subgraph 接入层 ["表现层与接入网关 (Client & Gateway Tier)"]
        A["普通数据库用户连接 (低权限账号)"] --> B["构造含匿名 RECORD 类型的并行查询"]
    end
    subgraph 规则层 ["查询规划与并行调度层 (Planner & Parallel Scheduler Tier)"]
        B --> C["生成并行计划 (Gather / Parallel Worker)"]
        C --> D["匿名 RECORD 类型标识符在 worker 间共享注册"]
    end
    subgraph 领域层 ["核心执行与内存生命周期层 (Executor & Memory Tier)"]
        D --> E["Worker A 释放共享 tuple descriptor"]
        E --> F["Worker B 仍持有旧地址并解引用 (Use After Free)"]
        F --> G["堆内存布局被可控数据覆盖"]
    end
    subgraph 存储层 ["基础设施与宿主层 (Host & OS Tier)"]
        G --> H["控制流劫持 / 任意代码执行"]
        H --> I[("以 postgres 系统用户权限落地")]
    end
  
图 1: PostgreSQL UAF 漏洞从低权限账号到宿主代码执行的完整触发链路,核心断裂点在于并行 worker 间共享元组描述符的释放时序竞争。

一、漏洞速览:PostgreSQL UAF 漏洞的官方定级与影响边界

根据 OSV 与 Ubuntu 安全公告,CVE-2026-116304 的 CVSS v3.1 向量为 AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H,综合评分 8.8(High)。Ubuntu 侧将其标记为 medium,这种评级差异恰恰反映了发行版视角与上游视角的分歧:Ubuntu 认为需要数据库账号作为前置条件,而上游更关注「一旦获得任意低权限账号即可提权至 OS」的严重性。

评估维度 官方取值 架构师解读 风险判定
攻击向量 AV Network 通过标准 SQL 连接即可触发,无需本地文件系统访问 远程可达
攻击复杂度 AC Low 无需复杂竞态窗口调优,并行计划本身即提供调度机会 易复现
所需权限 PR Low 任意可登录的数据库账号,业务只读账号亦满足 门槛极低
用户交互 UI None 无需管理员点击或配置变更 静默触发
机密/完整/可用性 H/H/H 可读取宿主文件、篡改数据、破坏服务 爆炸半径大
⚠️ 生产避坑风险

不要因为 Ubuntu 标注为 medium 就降低处置优先级。在多租户 SaaS、PaaS 数据库服务或存在弱口令/共享账号的环境中,PR:L 几乎等价于 PR:N,实际风险应以上游 CVSS 8.8 为准。

二、受影响版本矩阵与升级目标版本

漏洞影响 PostgreSQL 14 至 18 的全部主线版本,修复版本已随 2026 年 11 月的小版本发布同步上线。架构师在制定升级窗口时,需要同时核对上游版本号与发行版包版本号,避免出现「以为升了其实没升」的经典事故。

主线版本 受影响范围 修复版本 Ubuntu 20.04 包示例
PostgreSQL 18 < 18.7 18.7 —
PostgreSQL 17 < 17.12 17.12 —
PostgreSQL 16 < 16.16 16.16 —
PostgreSQL 15 < 15.20 15.20 —
PostgreSQL 14 < 14.25 14.25 —
PostgreSQL 12 (Focal) 12.0-1 至 12.22-0ubuntu0.20.04.4 发行版修复包 postgresql-12

需要特别注意的是,Ubuntu 20.04 LTS 上的 postgresql-12 属于社区已停止主线支持的版本,其修复依赖 Canonical 的扩展安全维护。若你的生产环境仍停留在 12.x,这本身就是一次架构层面的技术债清算信号——建议借此次应急窗口直接规划到 16 或 17 的跨大版本迁移。

三、根因剖析:匿名 RECORD 类型标识符在并行 Worker 间的协调缺陷

3.1 什么是匿名 RECORD 类型

在 PostgreSQL 中,RECORD 是一种伪类型,用于表示「运行时才确定结构」的行值。当查询中出现 ROW(1, 'a')、子查询返回多列、或 SELECT * FROM (VALUES ...) 这类结构时,执行器会为结果构造匿名的 tuple descriptor(元组描述符)。这些描述符在并行查询场景下需要被多个 worker 进程共享,因此其标识符与内存地址需要在共享内存或 DSM(Dynamic Shared Memory)段中协调。

3.2 UAF 的精确触发时序

漏洞的本质是「所有权语义缺失」:当多个并行 worker 引用同一个匿名 RECORD 类型标识符时,系统没有明确的引用计数或生命周期仲裁机制。攻击者可以构造一个查询,使得 Worker A 在完成自己的分片后释放共享 tuple descriptor,而 Worker B 仍持有该描述符的地址指针并在后续元组处理中解引用。此时该内存块可能已被重新分配并填充攻击者可控的数据,从而形成典型的释放后使用(Use After Free)。

  • 释放阶段:Worker A 认为匿名 RECORD 描述符仅属于自己,调用释放逻辑归还共享内存。
  • 悬垂阶段:Worker B 的本地缓存仍保存旧地址,未感知释放事件。
  • 重用阶段:攻击者通过并行查询的其他内存分配路径,将可控数据布局到同一地址。
  • 劫持阶段:Worker B 解引用被污染的描述符,函数指针或长度字段被篡改,控制流偏移。
💡 架构核心决策

这类缺陷无法通过 SQL 层权限模型防御,因为它发生在执行器内存管理层,位于所有行级安全(RLS)与列级权限之下。唯一可靠的防线是版本升级,任何「加权限、改配置」的思路都只是降低触发概率而非消除。

四、补丁逻辑与上游修复思路

上游在 18.7 / 17.12 / 16.16 / 15.20 / 14.25 中同步修复了该问题。从公开的发布说明与安全页面推断,修复方向集中在为匿名 RECORD 类型标识符引入明确的生命周期仲裁:要么在并行 worker 间建立引用计数,要么将描述符的所有权收敛到 leader 进程统一管理,worker 仅持有不可释放的只读引用。

# 1. 核验当前运行版本
psql -c "SELECT version();"

# 2. Ubuntu/Debian 系升级(以 PostgreSQL 16 为例)
sudo apt update
sudo apt install --only-upgrade postgresql-16 postgresql-client-16

# 3. 核验包版本是否达到修复线
apt-cache policy postgresql-16 | grep Installed

# 4. 重启服务使新二进制生效(小版本升级通常无需 initdb)
sudo systemctl restart postgresql

# 5. 升级后健康检查
psql -c "SELECT count(*) FROM pg_stat_activity;"
parallel_leader_participation = offINI

上述参数是临时缓解手段之一:关闭 leader 参与并行执行可以改变 worker 调度拓扑,降低特定竞态窗口的可利用性,但它不能替代升级,仅适用于无法立即重启的紧急窗口期。

点击展开:无法立即升级时的临时缓解脚本与回滚预案
# 临时缓解:全局关闭并行查询(性能有损,仅应急)
psql -c "ALTER SYSTEM SET max_parallel_workers_per_gather = 0;"
psql -c "SELECT pg_reload_conf();"

# 收紧账号权限:回收非必要账号的 LOGIN 与查询权限
psql -c "REVOKE CREATE ON SCHEMA public FROM PUBLIC;"

# 审计近期异常并行查询(需开启 pg_stat_statements)
psql -c "SELECT query, calls FROM pg_stat_statements WHERE query ILIKE '%RECORD%' ORDER BY calls DESC LIMIT 20;"

# 回滚:恢复并行配置
psql -c "ALTER SYSTEM RESET max_parallel_workers_per_gather;"
psql -c "SELECT pg_reload_conf();"

五、生产环境应急响应 SOP

针对 PostgreSQL UAF 漏洞,我建议按「资产盘点 → 风险分级 → 升级执行 → 验证闭环」四步推进,并在每个阶段留下可审计的证据链。

  • 资产盘点:扫描所有实例的 version() 输出,建立版本与业务归属映射,重点标记多租户与对外暴露的实例。
  • 风险分级:存在弱口令、共享账号、PaaS 自助开通能力的实例列为 P0,24 小时内完成升级。
  • 升级执行:优先采用滚动升级,主备切换验证后再升级原主库,避免单点中断。
  • 验证闭环:升级后复核包版本、执行并行查询冒烟测试、检查错误日志中是否有异常崩溃或段错误。
🚨 严重隐患告警

若实例日志中出现 segmentation fault、server process was terminated by signal 11 且伴随并行查询,需高度怀疑已被尝试利用。此时应立即隔离实例、保全内存转储与日志,并按入侵事件而非普通故障处置。

六、长期架构启示:把数据库内核 CVE 纳入 SLO 治理

这次 PostgreSQL UAF 漏洞再次提醒我们:数据库不是「装好就不动」的基础设施,而是持续演进、持续暴露攻击面的核心组件。成熟的团队应当把内核安全补丁纳入与业务服务同等级的 SLO 治理——设定高危 CVE 的修复时限(如 P0 24 小时、P1 7 天),并通过自动化流水线把版本核验、灰度升级、回滚演练固化为可重复执行的工程能力,而不是每次靠人工救火。

原文出处与权威溯源声明:
本文核心技术背景源自海外一线安全情报与上游公告:
OSV – UBUNTU-CVE-2026-116304 (Open Source Vulnerabilities)
PostgreSQL 官方安全页面 CVE-2026-116304

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注