2026 年 10 月 2 日,安全研究员 Haakon Wik Gulbrandsrud 公开了微软云端自动化服务 Azure Logic Apps 的五项跨租户漏洞细节,累计从微软拿走 20 万美元 漏洞赏金。这批漏洞包含 CVE-2026-70200 与 CVE-2026-83944 两个 CVSS 10.0 满分漏洞。在公有云里,不同企业客户的数据隔离是生死线,而这组漏洞允许攻击者越过租户边界,直接读写全球其他企业的 Azure Key Vault 密钥库、SQL 数据库以及关联的 Salesforce、Jira 等外部系统。目前五个漏洞已在云端全部修复,但这长达一年半的拉锯战暴露出一个更棘手的现实,微软对底层架构欠下的设计债,正在让打补丁变成一场按住葫芦浮起瓢的游戏。

共享网关的信任错位让外围补丁连遭五次绕过

理解这 20 万美元赏金的含金量,要先看清 API Connections 在 Azure 里扮演的角色。企业在用 Azure Logic Apps 搭建自动化工作流时,需要用 API Connections 存储外部系统的访问凭证。问题出在它的底层调用链上。当工作流发起请求时,流量会经过一个多租户共享的 Azure API Management(APIM)实例,由这个实例把手里的请求换成目标系统的真实令牌,再去访问后端数据库或 SaaS 服务。

封堵公开接口后,未写进文档的兄弟端点仍可直通核心密钥库(示意图)
封堵公开接口后,未写进文档的兄弟端点仍可直通核心密钥库(示意图)
Azure API Connections 跨租户越权调用路径 攻击者指令 篡改路径或参数 ARM 管理接口 拥有全局最高权限 共享 APIM 网关 置换任意租户令牌 受害租户后端 Key Vault / SQL 失守 核心缺陷:ARM 与共享 APIM 网关默认有权读取所有租户连接,仅靠外围输入校验拦截越权

这种设计在安全界被称为混淆代理人(Confused Deputy)。负责转发请求的 Azure Resource Manager(ARM)与共享 APIM 网关拥有访问全球所有租户连接的最高权限。只要攻击者能用参数欺骗网关,让它去查询别人的连接 ID,网关就会乖乖把受害企业的后台令牌交出来。

面对这种底层过度信任的架构,微软没有重做网关的权限隔离,而是选择了成本最低的办法,在入口处做路径字符过滤。这也直接导致了随后一连串令人啼笑皆非的攻防拉锯。

研究员第一次利用 DynamicInvoke 接口发起 ../ 路径遍历,成功读取了其他租户的 Key Vault 密钥。微软很快打上补丁,拦截了包含 ../ 的非正常路径。但研究员通过 SSH 登录到一台独占主机的标准版(Standard)Logic App 实例里,直接提取出底层运行代码,发现 DynamicInvoke 旁边还躺着三个完全没写进公开文档的兄弟端点,其中就包括 DynamicList。

因为微软当时只给公开接口加了黑名单,研究员把请求地址里的接口名换成 DynamicList,用同样的路径遍历逻辑,直接向其他租户的 SQL 数据库写入了恶意数据。微软随后封死了全部四个动态调用接口。

但只要底层共享网关依然默认信任上层传来的指令,堵死一扇门,攻击者只需要再找另一扇窗。研究员转头看向按量计费的消耗版(Consumption)Logic Apps。

隐式信任与补丁回归暴露出云端老旧组件的维护困境

在 AWS 或 GCP 等主流公有云的设计惯例中,无服务器工作流要访问敏感资源,通常会强制绑定一个细粒度的专属身份(如 AWS IAM Role),在底层做好硬隔离。Azure 新推出的标准版(Standard)Logic Apps 也是这么做的,它使用 V2 版连接,必须通过托管身份(Managed Identity)逐个授权。

标准版以托管身份做硬隔离,消耗版却靠薄弱的外围校验拦阻越权(示意图)
标准版以托管身份做硬隔离,消耗版却靠薄弱的外围校验拦阻越权(示意图)

但早期设计的消耗版(Consumption)Logic Apps 多个租户混跑在同一批机器上,使用的是 V1 版连接,根本没有专属身份可以授权。这导致所有消耗版实例在底层对全球所有 V1 版连接都拥有隐式访问权。拦在攻击者和全球企业数据库之间的,只剩下工作流运行时的一层输入校验。

Logic Apps 两代连接架构的隔离差距 V1 连接(Consumption 消耗版) 运行环境:多租户共享集群 身份机制:无独立托管身份 底层权限:默认隐式访问全部 V1 连接 防御完全依赖前端参数校验,一处绕过即全盘失守 V2 连接(Standard 标准版) 运行环境:单租户独占主机 身份机制:绑定专属托管身份 底层权限:按需显式授权单一连接 具备明确的租户级身份边界(但意外泄露了源码)

研究员在源码里翻出了一个名为 host.api.RuntimeUrl 的遗留参数。用户在配置工作流时,先填一个自己合法的连接通过归属权检查,随后在 RuntimeUrl 里直接填入受害租户的连接地址。只要域名以 azure-apihub.net 结尾,系统就会带着最高权限的认证头去请求受害者的地址。

底层没有零信任隔离,外围校验写得再厚也只是纸糊的围墙。

最能说明复杂系统修补难度的,是最后两个漏洞的诞生过程。微软为了堵住 RuntimeUrl 篡改,加了一条死规矩,要求传入的 URL 必须与当前合法连接的预期地址完全一致。但因为微软把校验时机放在了路径规范化(Path Normalization)之前,研究员在自己合法的连接地址后面拼接上 ../ 和受害者的连接 ID,前端校验一看前缀完全匹配就直接放行,到了后端 APIM 网关解析出相对路径,又一次跨租户拿到了别人的密钥。

等微软急忙修好这个路径遍历后,离奇的一幕发生了。新补丁直接把前一次写好的 RuntimeUrl 匹配校验给冲掉了,导致最早的直接替换 URL 攻击原样复活,研究员白捡了第五笔赏金。这种修新洞漏旧洞的回归故障,说明微软内部维护这套老旧连接架构时,不同补丁之间的代码逻辑已经高度缠绕,连自家的安全工程师都很难一眼看清全局副作用。


云端补丁之外企业安全团队必须自查的凭证盲区

这五项漏洞虽已在云端静默修复,无需企业手动升级安装包,但完全把安全寄托在云厂商的边界过滤上并不现实。一旦底层的混淆代理人架构没变,谁也不敢保证源码里没有第六个未公开的参数。

安全团队亟需将高权限个人凭证替换为最小权限的服务主体
安全团队亟需将高权限个人凭证替换为最小权限的服务主体

真正让这类漏洞杀伤力倍增的,是企业自身的配置习惯。API Connections 在对接外部系统时,权限大小完全取决于创建连接时填入的令牌。如果是用 OAuth 方式授权(比如对接 Salesforce 或 Jira),系统默认拿走的是创建者本人的全量权限;如果是填 API Key,绝大多数研发人员为了省事,直接塞进去一个拥有读写全权的管理员密钥。

  • 提醒.正在使用 Azure Logic Apps 的企业安全团队,最紧迫的动作不是打听微软怎么写了正则过滤,而是立刻盘点现存的 API Connections,把绑定的个人高权账号替换成仅具备最小读写权限的服务主体(Service Principal),并将敏感业务流从共享的 Consumption 消耗版迁移至通过托管身份做硬隔离的 Standard 标准版。

接下来最值得盯紧的变量,是微软会不会借这次付出去的 20 万美元学费,彻底废弃 V1 版连接那种全员隐式信任的旧架构,在 APIM 网关层引入真正的租户级令牌绑定。如果只是继续在外围堆砌路径黑名单,这场猫鼠游戏就远没有到终局。