导语:PostgreSQL 类型混淆漏洞 CVE-2026-18447 以 CVSS 8.8 的高危评分再次敲响数据库内核类型安全的警钟——一个看似无害的
any类型输出参数,竟能让仅有对象创建权限的低权用户,在数据库服务进程的操作系统用户身份下执行任意代码。本文从类型系统、函数解析链路与权限模型三层拆解这一漏洞的完整攻击面,并给出可直接落地的升级矩阵与应急 SOP。
一、漏洞全景:PostgreSQL 类型混淆漏洞的威胁画像
CVE-2026-18447 被评定为 High 级别,CVSS 3.1 基础评分为 8.8,向量为 AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H。这组向量传递出的信号非常明确:攻击者可远程发起、攻击复杂度低、仅需低权限、无需任何用户交互,且对机密性、完整性、可用性均造成高影响。
与常见的 SQL 注入或权限提升漏洞不同,本次问题的核心并非出在查询解析器或访问控制层,而是出在 SQL 语言函数的返回类型校验 这一相对冷门的内核路径上。攻击者只需要具备「创建对象」的权限(例如在自有 schema 下创建函数),即可构造一个输出参数声明为 any 类型的 SQL 语言函数,诱导服务端在类型推断与结果转换阶段发生类型混淆,最终突破数据库进程沙箱,以运行 PostgreSQL 的操作系统用户身份执行任意代码。
该漏洞的利用门槛极低:不需要超级用户,不需要文件系统写权限,不需要扩展安装能力。任何允许业务方或租户在库内创建函数的多租户架构、SaaS 平台、低代码平台,都属于高危暴露面,必须优先处置。
二、影响范围与版本矩阵
官方安全公告明确指出,所有低于以下修复版本的 PostgreSQL 均受影响。由于 PostgreSQL 采用多分支并行维护策略,五个大版本分支需要分别升级,运维团队务必按实际部署分支对号入座。
| 大版本分支 | 受影响版本 | 修复版本 | 升级紧迫度 |
|---|---|---|---|
| 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 14 已进入社区维护末期,部分发行版仓库可能不再提供 14.25 的二进制包。若无法升级至修复版本,必须启用下文所述的临时缓解措施,并将该实例纳入重点监控名单。
三、根因拆解:any 输出参数如何引发类型混淆
3.1 SQL 语言函数的执行链路
SQL 语言函数(LANGUAGE sql)在 PostgreSQL 中并非简单文本替换,而是会被解析为一棵内部的查询树,并在调用时以「内联展开」或「参数化执行」两种路径运行。函数定义中的参数类型(IN / OUT / INOUT)会参与函数签名解析、返回类型推断与结果元组构造。
当输出参数被声明为 any 这一伪类型时,类型系统在函数创建阶段无法确定具体目标类型,只能延迟到调用期进行动态推断。正是这段「延迟推断」的窗口,构成了类型混淆的温床:如果调用方传入的实际类型与函数体内部对参数的使用方式不一致,内核在结果转换阶段可能将一段内存按错误的类型解释,从而产生越界读写或函数指针劫持。
企业级架构规范
flowchart TD
subgraph 攻击面 ["攻击者接入层 (Attacker Tier)"]
A["低权限数据库账号 (CREATE 权限)"] --> B["创建 SQL 语言函数 (OUT 参数 any)"]
end
subgraph 解析层 ["函数解析与类型推断层 (Parser & Type Inference)"]
B --> C["函数签名注册 (伪类型 any 延迟推断)"]
C --> D["调用期动态类型绑定 (Type Binding)"]
end
subgraph 执行层 ["内核执行与类型转换层 (Executor & Coercion)"]
D --> E["类型混淆触发 (Type Confusion)"]
E --> F["内存错误解释 / 函数指针劫持"]
end
subgraph 影响层 ["宿主与基础设施层 (Host & Infrastructure)"]
F --> G["以 postgres OS 用户执行任意代码"]
G --> H[("数据泄露 / 持久化后门 / 横向移动")]
end
3.2 为什么是「对象创建者」而非「超级用户」
这是本漏洞最值得警惕的设计缺陷。传统认知中,能在数据库内执行代码通常需要 superuser 或 CREATE EXTENSION 等特权,而本次漏洞将攻击门槛下探到「对象创建者」——即任何拥有 schema 内 CREATE 权限的角色。在典型的多租户 SaaS 架构中,这意味着每个租户的数据库账号都可能成为攻击入口。
- 权限模型失配:函数创建权限与函数执行时的类型安全校验未形成闭环,创建阶段放行、执行阶段失控。
- 伪类型语义模糊:
any类型在 PostgreSQL 中本用于多态函数(如anyelement、anyarray),但 SQL 语言函数对其处理路径缺少严格的运行时类型断言。 - 沙箱边界薄弱:数据库进程与操作系统之间缺少额外的强制访问控制层,一旦内核被突破即直达宿主。
四、应急响应:从检测到修复的完整 SOP
4.1 第一步:资产盘点与暴露面识别
在动手升级之前,先要摸清家底。以下 SQL 可快速定位当前实例中是否存在使用 any 伪类型作为输出参数的 SQL 语言函数,这是最直接的暴露面信号。
-- 排查使用 any 伪类型作为 OUT/INOUT 参数的 SQL 语言函数
SELECT
n.nspname AS schema_name,
p.proname AS function_name,
pg_get_function_arguments(p.oid) AS arguments,
p.provolatile,
p.prosecdef
FROM pg_proc p
JOIN pg_namespace n ON n.oid = p.pronamespace
WHERE p.prolang = (SELECT oid FROM pg_language WHERE lanname = 'sql')
AND pg_get_function_arguments(p.oid) ~* 'banyb'
AND n.nspname NOT IN ('pg_catalog', 'information_schema')
ORDER BY n.nspname, p.proname;
-- 同时核查当前版本,确认是否落在受影响区间
SELECT version();
SHOW server_version_num;
若查询结果为空且版本已高于修复版本,可判定为安全;若查询结果非空但版本未升级,应立即冻结相关 schema 的 CREATE 权限,并进入升级窗口。
4.2 第二步:紧急缓解配置
在无法立即重启升级的生产环境中,可通过收紧权限与限制函数创建来争取时间窗口。以下配置建议写入 pg_hba.conf 与角色权限体系,形成纵深防御。
-- 1. 回收 public schema 的默认创建权限 REVOKE CREATE ON SCHEMA public FROM PUBLIC; -- 2. 为业务角色建立独立 schema,并仅授予必要权限 CREATE SCHEMA IF NOT EXISTS tenant_app AUTHORIZATION app_owner; REVOKE ALL ON SCHEMA tenant_app FROM PUBLIC; GRANT USAGE ON SCHEMA tenant_app TO app_user; -- 3. 审计并禁用可疑的 any 输出参数函数 -- (示例:将可疑函数重命名隔离,确认业务影响后再决定删除) ALTER FUNCTION tenant_app.suspicious_func(any) RENAME TO suspicious_func_quarantined;
回收 public schema 的 CREATE 权限可能影响依赖默认 schema 建表的应用。上线前务必在预发环境验证,并同步调整 ORM 或迁移脚本中的 schema 显式声明。
4.3 第三步:版本升级执行
根治手段只有一个:升级到对应分支的修复版本。以下给出基于主流包管理器的升级命令,生产环境请务必先在从库或预发验证。
点击展开:各发行版升级命令与回滚预案
# Debian / Ubuntu (PGDG 官方源) sudo apt update sudo apt install --only-upgrade postgresql-16 # RHEL / Rocky / AlmaLinux sudo dnf update postgresql16-server postgresql16-libs # 升级后重启并校验版本 sudo systemctl restart postgresql-16 psql -c "SELECT version();" # 回滚预案:升级前务必做物理备份 pg_basebackup -D /backup/pg_base_$(date +%F) -Ft -z -P # 若升级异常,使用备份目录 + 原二进制包回退,并核对 pg_control 版本号
五、方案对比:临时缓解 vs 彻底升级
面对 PostgreSQL 类型混淆漏洞,安全团队常陷入「先缓解还是先升级」的决策困境。下表从多个维度给出量化对比,帮助架构师做出取舍。
| 评估维度 | 仅权限收紧(临时缓解) | 升级至修复版本(根治) | 架构收益 |
|---|---|---|---|
| RCE 风险消除 | 部分降低,仍存绕过可能 | 完全消除 | 彻底闭环 |
| 业务侵入性 | 中,可能影响建表流程 | 低,小版本平滑升级 | 可控 |
| 实施耗时 | 分钟级 | 小时级(含验证) | 可规划 |
| 长期可维护性 | 差,需持续人工审计 | 优,回归官方支持基线 | 降本增效 |
临时缓解只能作为升级窗口期的过渡手段,绝不能作为长期方案。建议将「权限收紧 + 升级排期」组合执行,并在升级完成后重新评估 schema 权限模型,避免过度收紧影响业务迭代。
六、架构级反思:数据库内核安全的长期防线
PostgreSQL 类型混淆漏洞并非孤例,它折射出数据库内核在「灵活类型系统」与「严格安全边界」之间的永恒张力。作为架构师,我们应从三个层面构建长期防线:
- 最小权限常态化:默认回收
publicschema 的 CREATE 权限,业务角色按 schema 隔离,杜绝「人人可建函数」的宽松模型。 - 版本基线自动化:将 PostgreSQL 小版本纳入 CI/CD 的依赖扫描,订阅官方安全公告 RSS,确保高危补丁在 72 小时内进入升级队列。
- 运行时纵深防御:在数据库进程外叠加 SELinux/AppArmor 强制访问控制,即便内核被突破,也能限制攻击者的横向移动半径。
最后提醒:任何涉及 any、anyelement 等多态伪类型的自定义函数,都应在代码评审阶段被标记为「安全敏感代码」,由 DBA 与安全团队联合评审后方可上线。类型系统的灵活性是 PostgreSQL 的核心竞争力,但灵活性必须被约束在明确的权限与审计框架之内。
本文核心技术背景源自 GitHub Advisory Database 与 PostgreSQL 官方安全公告:
GHSA-76fw-fh4f-3w66 (GitHub Advisory Database)
PostgreSQL 官方安全公告 CVE-2026-18447
