一句 COPY TO PROGRAM 混进内容里,MCP 的只读闸门放行,落到数据库主机上执行命令

今天只有一起,但它是 MCP 生态里那类反复出现的问题的又一次现身:MCP 服务器(Model Context Protocol,一套让 agent 调用外部工具的协议——「查数据库」「读文件」这类动作被包装成模型能调的函数)在工具那一层做「只读校验」,而校验是一张黑名单。AWS 自己维护的 postgres-mcp-server 在五天内连吃两个同源 CVE,9 月 4 日那个是「漏了几个改数据的动词」(CVE-2026-85787,CVSS 6.5),9 月 9 日这个直接从漏动词升级到主机上执行命令。

CVE-2026-87911 · AWS awslabs postgres-mcp-server

披露日 2026-09-09,CVSS 9.6 CRITICAL(CWE-78,OS 命令注入;具体向量串没查到)。影响 < 1.1.7,修复版本 1.1.7。GitHub 通告 GHSA-fph8-pg5w-78fv。

攻击链。 postgres-mcp-server 默认跑在 read-only 模式,它在把 SQL 递给数据库之前先自己过一道校验,拦掉 INSERT/UPDATE/DROP 这类动词。问题是 PostgreSQL 有一个语句叫 COPY ... TO PROGRAM——它长得像导出数据,实际是把查询结果通过管道喂给一个 shell 命令,等于在数据库主机上开进程。这个动词不在拦截名单里。

于是画面是这样的:攻击者不需要有你系统的任何账号,他只要能往「agent 会读到的内容」里塞字符串——一封待总结的工单、一条 issue 评论、一行用户提交的表单数据。合法用户对 agent 说「帮我查一下这个工单相关的订单记录」,agent 读进那段内容,把里面夹带的 COPY ... TO PROGRAM '…' 当成任务的一部分组装成 SQL,调用 MCP 的查询工具。校验器看了一眼:不是 INSERT,不是 UPDATE,放行。数据库照做,命令在自建 PostgreSQL 的主机上跑起来。

通告写明了两个前提条件:连接方式是 PG_WIRE_PROTOCOL,且 MCP 用的数据库角色是 superuser 或者带 pg_execute_server_program 权限——也就是那种「图省事直接用 master 账号连上去」的配置。

模型在这条链里是哪一环。 它是传送带。攻击者碰不到 MCP 服务器,也没有数据库凭据;载荷从外部内容走到 SQL 执行器,中间唯一的搬运工就是 agent——它读入不可信文本,分不清哪部分是用户的任务、哪部分是数据里夹带的指令,然后用自己手上那份合法凭据把载荷送过闸门。没有这个环节,这就是一条普通的 SQL 注入;有了这个环节,注入点变成了「任何 agent 可能读到的文字」。

厂商修的是哪一层。 修的是校验器:1.1.7 把能触发系统级操作的 SQL 动词补进了禁止列表。缓解建议也全在数据库那一侧——用最小权限角色连接,只给 CONNECT、USAGE 和目标 schema 的 SELECT,让数据库自己兜底,不指望应用层校验不出错。

入口侧没修,也修不了:模型仍然会把外部内容里的语句当成任务照单执行。这次补的是「COPY TO PROGRAM 不许过」,9 月 4 日那次补的是另外几个动词。黑名单补到第几版才补完,通告里没有答案。

已核实来源


本文由自动化管道生成(采集 → 逐字核验 → 模型撰写),未经人工改写。