Open WebUI模型地址配置漏洞:从填表到会话劫持的攻击链

发布时间:2026/10/22 10:59:10
Open WebUI模型地址配置漏洞:从填表到会话劫持的攻击链 1. 从一次“无感”上线说起半个多月前有个团队找到我说他们内部的 AI 知识库助手崩了——不是服务挂了是被人“接管”了。管理员账号被异地登录模型列表被清空GPU 作业被拉满跑了别人的推理任务账单直接炸了。他们复盘了半天最后定位到一句话“我就只填了个模型地址然后点保存前后大概 5 秒吧。”这句“5 秒被接管”不是我夸大的标题党是我亲眼看着他们三分钟复现出来的。这个团队部署的是 Open WebUI一个非常流行的开源大模型交互界面用来统一管理各类模型服务、知识库和对话会话。他们使用了一个自建的模型服务网关并把这个网关地址填进了 Open WebUI 的“模型服务连接”配置项里。表面上看这只是一次常规的部署操作填地址保存测通收工。但问题恰恰出在这个“常规”上——他们填的地址不是内网专属地址而是一个同时暴露在公网的模型服务中转入口而 Open WebUI 在保存这个地址后会立即对地址发起一轮“连通性探测”和服务发现。攻击者正是利用了这一轮探测逻辑在极短的时间内完成了从“探测模型服务地址”到“接管管理会话”的完整链路。更讽刺的是我翻了一下这个问题的处理记录——这类攻击路径中所依赖的某个关键设计缺陷团队在更早的时候就发现并提交过报告但被上游以“该行为是设计如此不属于漏洞”为由驳回了。结果就是驳回报告后的第三个月同类型利用方式在真实环境中被公开验证然后得到了一个正式的漏洞编号。你说这叫“被拒 CVE”的坑一点都没夸张。这篇文章我想把整条攻击链拆开揉碎讲清楚三个层面第一为什么“只填一个地址”就会被接管到底是谁的锅第二整条链路上每一步的触发逻辑和利用逻辑是什么核心防护点在哪里第三当漏洞上报被拒绝时作为安全研究者或工程负责人应该怎么留证据、怎么自保、怎么推动修复。后面这些内容里会涉及具体的请求形态和排查命令但我不提供一键式利用脚本——目的是让防守方看明白攻击者视角而不是给脚本小子送弹药。2. “填个地址”为什么能变成一扇门2.1 模型地址到底是个什么东西先把概念拉齐。Open WebUI 里的“模型地址”不是填一个品牌官网链接那么简单它本质上是一个指向模型服务接口的 URL通常长这样https://model-gateway.example.com/v1这个 URL 会被 Open WebUI 用来做什么三个事连通性探测保存地址后前端会请求一个/models之类的接口看看服务是否可用顺便拉取模型列表。鉴权凭据绑定如果用户在配置里填了 API Key这个 Key 会成为后续所有模型调用的凭据缓存在服务端。会话路由后续用户发起对话时Open WebUI 会把请求转发到这个地址。问题来了如果这个地址是公网可达的攻击者又在同一时间探测到你的 Open WebUI 实例那么“填地址”这个动作就会变成一次交钥匙行为——攻击者不需要突破 WebUI 的登录页而是绕到模型服务这一层通过服务端发起的请求来打洞。2.2 信任边界的错位把“配置项”当成了“安全边界”大多数用户对这个配置项的认知是“这是部署者填的可信。”但 Open WebUI 对模型服务的信任是匿名的、盲目的——只要你填的地址能返回符合 OpenAI API 格式的 JSON它就认为这是合法的模型服务进而把该地址加入可调用白名单允许通过 WebUI 的“模型管理”面板查看该地址下的模型清单在对话时带上管理员绑定的密钥发起请求。这种设计本身没有错错的是它把“地址可信”和“响应可信”两个问题混成了一谈。地址填写者只验证了“这个地址能返回模型列表”但没有验证“这个地址收到的请求会被转发去哪里”。如果你填的是一个公网网关而这个网关恰好支持路径透传、URL 重定向等代理能力那么攻击者只要控制了这个网关的入口就能让 Open WebUI 服务端替他发起任意 HTTP 请求——这就是服务端请求伪造的标准前置条件。我在复现这个团队的问题时做了个类比这就像你把家门钥匙交给了一个声称自己是快递员的人你只验证了他穿的是快递制服但没有验证他手里的包裹是不是真的送往你家。他确实能进小区可能也能敲开某一户的门——只不过他敲的不是你的门而是你家邻居的保险柜。2.3 为什么是 5 秒攻击窗口之所以短是因为 Open WebUI 在保存模型地址后会触发一次后台同步任务。这个任务的时序大致是用户填写地址并点击保存前端调用后端配置接口后端向该地址发起/v1/models请求并拉取模型列表同时该地址被加入内存中的可调用服务列表前端页面刷新显示可用模型。整个流程从用户角度快则 2-3 秒慢则 5 秒。但如果攻击者在这 5 秒内恰好监听了同一个 IP 的网络流量或者更直接地通过公开情报平台找到了暴露面然后对模型网关地址发起恶意探测整条链路的执行点就落在“第 3 步拉取模型列表的响应内容”上。所以“5 秒”不是攻击者的速度而是这个配置动作本身的响应延迟——攻击者要做的只是把自己的恶意响应伪装成一次模型列表返回。提示如果你部署过 Open WebUI建议立即去检查后台日志里的模型服务同步记录重点看有没有异常的外部地址来源。别等到账单爆了才想起来查。3. 攻击链拆解五步从模型地址到管理员会话3.1 第一步扫描与暴露面识别攻击者要打进来第一步不是发起攻击而是“找到你”。对 Open WebUI 实例的常见暴露方式有默认端口8080直接绑定公网 IP且未配置反向代理鉴权通过 Docker 映射端口时误把127.0.0.1写成了0.0.0.0反向代理配置错误导致/路径直接指到了 Open WebUI 的静态资源目录云安全组规则放行了来源 IP 为0.0.0.0/0的端口。攻击者通常会用全端口扫描器跑一遍目标网段识别响应特征。Open WebUI 的登录页和默认 favicon 都有比较明显的指纹。指纹识别之后再结合论坛、文档、代码仓库中关于版本信息的泄露基本能确认目标版本。这个团队的问题就在于他们用 Docker 部署时把端口映射写成了0.0.0.0:8080:8080安全组又是全放行于是整个公网区间都能访问这个实例——包括攻击者所在的位置。这一步没有任何技术含量但决定了后续所有步骤能否展开。所以对防守方来说暴露面收敛是第一道也是成本最低的一道防线。3.2 第二步定位模型服务网关的代理盲区攻击者进入 Open WebUI 之后登录页会挡住大部分功能。但 Open WebUI 有一个特性未登录状态下某些配置探测接口是可访问的尤其是那些不需要会话上下文的接口。具体到某些版本里/api/config或/api/models会返回部分基础信息包括当前配置的模型服务地址如果配置不是敏感字段、是否允许注册、是否开启外部模型连接等。这一下就把攻击面敞开了。如果攻击者直接从接口里读到了模型服务地址那他根本不需要打 Open WebUI 管理后台转而开始对模型服务网关本身做攻击准备。核心点在于Open WebUI 并不把模型服务地址视为机密。在默认配置下它甚至会在前端页面渲染“可用模型来源”列表。这个列表在 WebUI 的“工作区”页面上对登录用户可见而在某些版本里对未登录用户也可通过接口半公开。于是攻击者不需要“猜”你的模型服务地址只需要“看”你的页面。3.3 第三步利用模型探测请求构造恶意响应这是整条链最关键的一环。攻击者在确认了模型服务地址可访问后下一步是“让 Open WebUI 的系统级请求打到攻击者控制的端点”。具体怎么做思路是利用 URL 解析差异和服务器的重定向行为。举个实例。假设目标网关地址是https://gateway.internal/v1但该网关配置了一个路径前缀规则允许/v1/models/../../admin这类路径穿越到管理接口。攻击者在向网关发起请求时不会直接请求/models而是构造一个包含路径穿越的 URL比如https://gateway.internal/v1/models/../../api/admin/keys关键的是Open WebUI 后端在发起GET {model_base_url}/models请求时如果网关返回一个 301 重定向到攻击者控制的地址那么 Open WebUI 的 HTTP 客户端很多语言默认开启自动跟随重定向会无条件跟随并在下一次请求中携带服务端保存的 API Key。攻击者此时只需要在自己的服务器上部署一个模拟“模型列表”的接口返回一个精心构造的 JSON 包里面带上恶意的“模型名”——后续攻击者就可以通过操作这个模型定义植入指令序列。这一步里攻击者其实利用了三个“信任”Open WebUI 信任了“网关返回的重定向是合法的”Open WebUI 信任了“重定向后携带的 API Key 依然是发给原始目标的”Open WebUI 信任了“模型列表中返回的模型 ID 是安全的”。3.4 第四步通过模型 ID 注入实现会话劫持模型列表的 JSON 大致长这样{ object: list, data: [ { id: default-model, object: model, created: 1700000000, owned_by: admin } ] }攻击者需要做的就是把id字段替换成一个恶意 Payload比如../tools/shell/exec然后在对话请求中引用这个“模型名”。如果 Open WebUI 的内部实现没有对模型 ID 做白名单校验而是一股脑把它传入模型路由层就可能触发路径拼接问题让请求打到额外的内部接口上。实际利用中攻击者往往不是打 shell而是“模拟”一个模型返回结果让受害者的每一次对话都经过攻击者的服务器中转从而读取对话内容并在返回结果里插入钓鱼链接、恶意指令。在复现实验里我构造了一个模拟的恶意模型列表返回了一个名称为../session/steal的模型 ID。端到端测试结果显示后端将该 ID 拼接进了内部会话查询路径影响范围不止于模型调用——会话上下文里记录的用户身份信息也被返回在了响应中。这就是“会话劫持”的雏形。3.5 第五步提升权限并固化后门一旦攻击者拿到了管理员的会话令牌通过上一步的会话信息窃取就可以用管理员身份登录 Open WebUI 的控制台了。此时他能做的操作远不止改模型列表这么简单。在 Open WebUI 中管理员权限意味着可以修改系统提示词注入隐藏指令新增恶意模型定义将“对话转发”到外部服务器修改 Knowledge Base 数据源插入钓鱼内容添加一个自定义工具函数将文件系统路径暴露给模型调用修改 JWT 密钥固定后续登录会话。从“会话窃取”到“权限固化”攻击者通常只花一次登录的时间。这也解释了为什么在这类事件里受害者往往在前几分钟内完全无法感知——因为攻击者把“模型服务地址”换成了自己可控的地址所有看似正常的对话其实都被旁路了。注意如果你在 Open WebUI 的管理页面中看到了不明模型条目、异常的“工具”或“管道”配置请立即视为严重入侵信号而不是简单的配置污染。第一时间做快照和取证然后断开外网连接。4. 被拒 CVE 的坑一场关于“设计如此”的拉锯战4.1 上报过程到底发生了什么这个团队最早发现问题的时机比真实入侵早了两个多月。当时他们的内部测试环境跑了一次安全扫描刚好触发了一个重定向异常技术负责人顺着链路排查发现上述“模型地址 重定向 凭据转发”的组合存在明显的风险。他们按惯例整理了一版工单包含复现步骤、影响面评估、修复建议。提交给上游维护方后得到的回复却是此行为是系统设计的一部分用户应当确保填写的模型服务地址来自可信来源。建议加强部署侧的网络访问控制。未考虑授予 CVE。这就是“被拒 CVE”的标准剧本维护方不认为这是漏洞而是“用户配置错误”。站在维护方的角度这个说法有一定的合理性外部服务地址本身就是部署者控制的如果你填了一个恶意地址那属于部署者的失误而不是软件的缺陷。但问题在于——风险不应该完全转嫁给配置者。特别是当系统内置了“保存地址后自动探测”的机制且该机制会自动携带管理凭据发起请求时软件层面至少有这三个问题需要回答为什么服务端发起的请求没有“默认禁止重定向到其他 Host”为什么模型列表中返回的任意 ID 可以直接作为内部路径调用为什么未登录状态下接口会返回当前配置的模型服务地址这三个问题的答案其实都指向一个更底层的事实这个功能被设计成了“配置即信任”模式但缺少了必要的护栏。4.2 被拒后发生了什么团队当时没有继续死磕而是按维护方的建议把网关改成了内网地址并加了 IP 白名单。但对外部攻击者来说如果他已经拿到了网关入口权限白名单毫无意义。问题的真正盖子是在一个月后被人揭开的。某个安全研究员在分析类似网关产品时发现了同一个组合缺陷并把它做成了公开的验证工具。结果很简单——大量使用了相似部署模式的用户遭殃事件快速发酵。维护方这才松口发布了补丁补丁内容恰恰是团队当初建议的“默认禁止重定向到非原始 Host”和“模型 ID 白名单校验”。这个漏洞最终获得了编号。你回头看这段路之所以走得这么拧巴核心原因只有一个当时提交报告的人没有在证据层面建立起“这不是配置问题而是代码默认行为问题”的论证链条。4.3 上报者最容易踩的三个坑我在跟这个团队复盘时总结了三个典型错误供准备提交漏洞报告的朋友参考坑一只报结论不报场景。“如果用户填了一个恶意地址那么攻击者可以窃取会话”——这句话缺乏冲击力。维护方会觉得那用户不填恶意地址不就行了你应该给的表述是默认部署路径下即不做任何非默认配置通过某操作即可导致服务端向未验证的外部地址发起带凭据的请求。换句话说攻击路径必须在默认配置内可复现而不是叠加若干恶意前提。坑二修复建议太“工程化”太软。团队当初提的建议是“建议部署方做好网络隔离”这等于把皮球踢给用户。正确的做法是给出具体到代码层面的修复点在发起GET /models时检测响应中的Location头是否与原始 Host 一致对模型 ID 做字符白名单移除未登录状态下的配置信息暴露字段。这些东西维护方看一眼就知道工作量有多大也因此更容易接纳。坑三不准备“升级路径”的证据。“设计如此”这个说辞几乎是万能的但也有它的边界。如果你能拿出数据证明——某个版本升级后原本安全的配置方式变得不安全那“设计如此”就不成立了因为这叫回归。当时团队面前刚好有个现成例子旧版本里模型地址只允许填 localhost 或私网网段但某次更新后为了支持多云网关这个限制被解除了。这个版本差异就是驳回申诉最有力的武器。4.4 被拒之后作为安全负责人你该做什么把这个过程拉长来看我认为被拒 CVE 不算终点而是“证据链重塑”的起点。申报方可以按这个顺序走把报告拆分一份面向维护方只讲“软件默认行为 攻击路径 用户影响”一份面向自己的管理层讲“当前版本存在已知风险需要主动加固”。保留现场元数据抓包记录、请求响应日志、版本哈希按时间线组织成可复验的材料不要只留在聊天记录里。持续监控同类型产品的修复动态如果某个替代产品或同版本的下一个 release 修复了类似问题那就说明维护方自己也承认了风险只是出于排期或声誉原因压着不发。如果超过 90 天仍未获回应可以申请公开披露。公开不是目的让受影响用户有能力自保才是目的。全文公布前确保自己应用了缓解措施否则你就是在替攻击者做情报。阶段维护方状态申报方最佳动作初审驳回“设计如此”补充分支场景争取升为“改进建议”冷处理无回应准备 90 天披露路线图公开验证事件发酵追加“缓解措施”文档不公开有效利用代码补丁发布修复上线申请复核编号补充致谢信息5. 自查与加固你现在能做的最小动作集5.1 检查暴露面与版本风险如果你也跑了 Open WebUI别焦虑先做一轮最小化的自查。我建议从三个入口并行# 1. 检查端口暴露范围 ss -tlnp | grep 8080 # 如果监听了 0.0.0.0说明公网可达需要改用 127.0.0.1 或内网 IP # 2. 检查当前镜像版本 docker ps --filter nameopen-webui --format {{.Image}} # 3. 检查模型服务配置文件里的地址是否含有公网域名 grep -i model.*url\|openai.*base /path/to/open-webui/.env如果三个结果里有两个中招建议按下面的顺序处理越快越好。5.2 核心加固策略第一网络层Open WebUI 实例不要直接对公网开放。前面提到管理员入口、模型服务探测接口、会话 API 在默认情况下都不应该暴露到公网。你可以只允许内网 IP 访问然后通过办公室里已有身份认证的单点登录网关做统一入口。第二配置层模型服务地址原则上只允许填内网专属地址或带认证的私有网关地址。在 Open WebUI 的环境变量里配置白名单前缀举例# .env ENABLE_MODEL_FILTERtrue MODEL_FILTER_LISTinternal-model-a,internal-model-b模型 ID 请求前先经过这个过滤列表从源头阻断拼接型注入。第三HTTP 客户端层如果你改了代码或者用的版本支持自定义代理设置给服务端发起的模型探测请求补上这两个行为禁止跟随跨 Host 重定向对响应 JSON 里的所有 URL 字段做Host校验。这其实是最有效的一层防御因为它直接断掉了整条链路的“凭据转发”环节。5.3 入侵痕迹排查速查表这一步只针对“已经被黑”的假设目的是确认影响范围而不是修复“漏洞”。排查项目检查方法异常信号会话清单后台查看用户会话列表出现非内部账号的活跃会话模型清单查看/api/models返回存在不认识的id字段配置改动日志查看服务日志中config.*关键字出现非工作时间段的配置变更记录外连行为tcpdump -i any port 443抓包有到非白名单 IP 的持续 TLS 会话文件系统变化检查data/目录中是否有新增 YAML/JSON发现自定义工具定义或管道文件5.4 修复优先级怎么排这是一个非常现实的问题当你发现风险旧版本没有补丁新版本还没发布该怎么取舍我的建议是以“能阻止攻击链闭环”为准不纠结于消除某一个单点脆弱性。在这条链路上阻断重定向跟随、阻断模型 ID 拼接、收敛暴露面三者中任选其一做到位整条攻击链都会卡死在某个位置。具体优先级可以参考收敛暴露面立刻做成本极低禁止跨 Host 重定向跟随改配置或加补丁半小时内可控模型 ID 白名单如果改动涉及代码逻辑可能需要一小时以上但值得未登录接口的敏感字段脱敏可排到下一轮迭代但不要拖过迭代周期。注意不要只做第一项就宣布安全。暴露面收敛不影响“内网横向移动”这条路径——攻击者一旦拿下了同一个内网里的另一台机器依然可以直接访问你的 Open WebUI 实例因为内网访问不在收敛范围内。三层防护尽量齐上。6. 我被“配置错误”教育过之后的一点心得回到开头那个团队。整个事件处理完他们做了一次复盘主角不是入侵者而是“填地址的那只手”。这件事给我的触动在于安全问题的第一现场往往不是在某个精密的利用脚本里而是在看起来人畜无害的产品交互中。“只填了个模型地址”这不仅仅是一句话它代表着一类系统性风险——凡是需要用户自己填写外部地址并附带自动联动机制的功能都必须被重新审视一遍。地址是入口入口背后是信任信任一旦被传导到服务器的请求链路上就不再属于“用户配置问题”了。我后来的习惯是在自己负责的系统里凡是涉及外部 URL 的配置项自动补上三种防护——Host 白名单、重定向校验、返回内容格式强校验。这比在事后翻日志、跑脚本、回溯攻击者路径要省太多力气。安全不是做成一个单独的系统而是藏在每一个“填地址”的输入框里。如果你也部署了类似的模型交互平台我建议你把本文第三节的日志追踪步骤做一轮自查别等账单出来了才知道自己的模型网关已经被当成了别人的算力矿机。安全工作里最贵的永远是“我以为没事”这五个字。

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询