CVE-2025-68668漏洞分析:n8n工作流自动化平台Pyodide沙箱逃逸与命令执行

CVE-2025-68668漏洞分析:n8n工作流自动化平台Pyodide沙箱逃逸与命令执行 1. 项目概述当工作流自动化遇上代码沙箱逃逸最近在梳理一些开源自动化工具的安全边界时一个编号为CVE-2025-68668的漏洞引起了我的注意。这个漏洞发生在n8n这个近年来非常流行的开源工作流自动化平台上核心问题出在它集成的Pyodide组件上最终导致了远程命令执行。对于任何在生产环境中部署了n8n尤其是允许用户自定义JavaScript代码节点的团队来说这个漏洞的潜在风险不容小觑。简单来说攻击者可以利用这个漏洞通过精心构造的输入让n8n服务端执行任意系统命令从而完全控制服务器。今天我就结合自己的复现过程把这个漏洞的来龙去脉、触发条件、利用方式以及关键的防护思路给大家掰开揉碎了讲清楚。无论你是n8n的运维人员、安全研究员还是对自动化工具安全机制感兴趣的开发者这篇文章都能帮你建立起对这个漏洞的完整认知。n8n本身是一个强大的、基于节点的可视化工作流工具它允许用户通过拖拽连接不同的节点如HTTP请求、数据库操作、逻辑判断等来构建复杂的自动化流程。为了提供极致的灵活性n8n内置了“Code”节点支持用户编写JavaScript或Python通过Pyodide代码来处理数据。Pyodide是一个将Python运行时编译到WebAssembly并在浏览器中运行的项目n8n利用它实现了在Node.js服务端环境中安全地执行用户提交的Python代码。然而CVE-2025-68668正是打破了Pyodide试图构建的这层“安全沙箱”。在深入技术细节之前我们先明确一点这个漏洞的利用前提是攻击者已经拥有在n8n工作流中创建或编辑“Code”节点的权限。这通常意味着攻击者要么是一个具有相应权限的已登录用户要么通过其他漏洞如CSRF、权限提升获得了这个能力。因此它的威胁模型更偏向于“内部威胁”或“权限滥用后的横向移动”。2. 漏洞原理深度拆解Pyodide沙箱的“裂缝”要理解CVE-2025-68668我们必须先搞明白n8n中Pyodide的工作机制以及它理想中的安全边界。这不是一个简单的输入验证绕过而是涉及到底层能力暴露的沙箱逃逸问题。2.1 n8n中Pyodide的集成架构在n8n的架构中当你在一个“Code”节点中选择使用Python时你写的代码并不会被直接发送到服务器的原生Python解释器中执行。相反n8n会在一个独立的Node.js子进程里启动一个Pyodide实例。Pyodide核心是一个WebAssembly模块它包含了一个完整的、功能受限的CPython解释器。用户提交的Python代码就在这个WASM沙箱环境中被解释执行。设计初衷是美好的WASM内存隔离、无直接系统调用能力理论上应该很安全。n8n的Pyodide执行环境还预先注入了一些有用的对象比如output用于输出数据以及一个_对象通常指lodash库等方便用户脚本使用。然而Pyodide为了使其在浏览器外如Node.js也能工作并提供一些必要的交互能力它暴露了一个名为pyodide的全局对象或者通过特定API可以访问到一些底层功能。关键点在于Pyodide提供了与宿主环境Node.js进行交互的通道。一个重要的接口是pyodide.runPython或pyodide.runPythonAsync它们不仅能运行代码还能在Python和JavaScript之间传递对象。更危险的是Pyodide允许JavaScript代码调用Python函数反之亦然并且可以访问一些“内建”模块。2.2 漏洞核心被暴露的importlib与sys模块漏洞的根源在于在n8n集成的Pyodide环境中攻击者可以通过Python代码访问到本应被严格限制或清理的模块特别是importlib和sys。在标准的浏览器Pyodide环境中许多可能用于逃逸的模块如os,subprocess要么不存在要么功能被阉割。但importlib是Python导入系统的核心如果它能被完整使用就可能成为一个“万能钥匙”。通过importlib攻击者可以尝试导入不在默认沙箱白名单中的模块。而sys模块则提供了对Python解释器运行时环境的访问包括sys.modules字典所有已加载模块的缓存和sys.path模块搜索路径。在完整的CPython中通过sys可以接触到许多底层接口。在n8n的漏洞版本中攻击者编写的恶意Python脚本能够利用importlib.import_module或__import__函数尝试导入os、subprocess、socket等敏感模块。由于Pyodide运行在Node.js子进程中而Node.js子进程本身具有执行系统命令的能力通过child_process模块一旦Python层能够触碰到这些能力沙箱就被打破了。一种典型的利用链是在Python中导入os模块然后调用os.system()或os.popen()。在普通的Pyodide for Web中这些调用会失败或不存在。但在n8n的特定集成环境下由于Pyodide与Node.js宿主环境的特殊绑定关系这些调用可能被桥接到宿主环境最终导致在运行n8n服务的服务器上执行命令。注意复现的具体利用方式可能因n8n和Pyodide的版本而异。有些利用可能需要通过sys模块修改某些属性或利用Pyodide提供的js对象用于访问JavaScript命名空间来间接调用Node.js的child_process模块。核心思想始终是从Python沙箱内部找到一条路径来调用宿主Node.js环境的系统命令执行功能。2.3 与常见漏洞模式的对比这个漏洞不同于典型的“模板注入”或“代码注入”。它不是将未过滤的用户输入拼接进动态执行的代码字符串如eval(input)。相反它是在一个预期允许执行代码的上下文Code节点中利用了沙箱本身的不完整性。沙箱提供了执行Python的能力但未能彻底切断所有通向危险底层功能的路径。这更像是一种“权限配置错误”或“安全边界模糊”属于设计或实现上的缺陷而非简单的输入过滤疏忽。这也使得传统的WAFWeb应用防火墙基于特征匹配的规则很难防御因为攻击载荷本身就是合法的Python代码片段。3. 漏洞复现环境搭建与验证理论讲得再多不如亲手实践一遍。下面我详细记录一下在受控环境中复现CVE-2025-68668的完整过程。再次强烈警告所有操作必须在完全隔离的虚拟机或实验环境中进行严禁对任何非授权系统进行测试。3.1 实验环境准备我选择使用Docker来快速搭建一个存在漏洞的n8n环境这是最接近真实部署场景且易于还原的方式。确定漏洞版本根据CVE描述和社区信息该漏洞影响n8n 1.71.0及之前的一些版本。我们选择n8nio/n8n:1.70.0这个镜像进行复现。启动脆弱版n8n容器docker run -it --rm \ --name n8n-vuln \ -p 5678:5678 \ -e N8N_BASIC_AUTH_ACTIVEtrue \ -e N8N_BASIC_AUTH_USERadmin \ -e N8N_BASIC_AUTH_PASSWORDpassword \ -v n8n_data:/home/node/.n8n \ n8nio/n8n:1.70.0这里我们开启了基础认证用户admin密码password并将Web服务端口5678映射到宿主机。数据卷用于持久化配置。访问与登录启动后在浏览器中访问http://localhost:5678使用上面设置的用户名密码登录进入n8n的主界面。3.2 构造恶意工作流进行复现复现的核心是创建一个包含恶意Python代码的“Code”节点。创建新工作流在n8n控制台点击“New”创建一个空白工作流。添加“Code”节点从节点面板中搜索并添加一个“Code”节点到画布上。配置Code节点Mode: 选择Python。Code: 在代码编辑框中输入我们的测试载荷。一个相对直接且经典的测试载荷是尝试执行系统命令。例如我们可以尝试列出根目录文件import os result os.listdir(/) output [{result: result}]但是在存在漏洞的环境中攻击者可能会尝试更直接的命令执行。请注意以下载荷仅为教学演示展示了可能的利用方式# 尝试利用subprocess执行命令 try: import subprocess # 执行一个无害的命令如打印当前工作目录 cmd_result subprocess.check_output(pwd, shellTrue, textTrue) output [{status: success, output: cmd_result}] except Exception as e: output [{status: error, message: str(e)}]或者更隐蔽地通过importlib动态导入import importlib # 尝试导入os模块并执行命令 os importlib.import_module(os) # 执行id命令查看当前进程用户 user_info os.popen(id).read() output [{user_info: user_info}]执行与观察点击节点右上角的“Execute Node”按钮。如果环境存在漏洞节点将成功执行并在“Output”面板看到命令执行的结果例如当前工作目录路径或用户ID信息。如果沙箱是完好的你通常会看到一个导入错误如ModuleNotFoundError: No module named os或一个执行被禁止的错误。实操心得在实际测试中由于Pyodide版本和n8n封装的具体差异直接导入os或subprocess可能不会成功。有时需要更迂回的方式例如通过sys模块找到已加载的模块或者利用Pyodide提供的js全局对象来访问Node.js的require函数进而加载child_process模块。这需要一些对Pyodide和Node.js交互机制的了解。一个更高级的测试载荷可能长这样import sys # 检查sys.modules中是否有可利用的模块 output [{modules: list(sys.modules.keys())}]通过这个输出你可以观察沙箱内实际可用的模块列表从而寻找突破口。3.3 复现结果分析与验证如果测试载荷执行成功并返回了系统命令的结果那么漏洞复现就成功了。这证明了沙箱逃逸发生Python代码成功突破了Pyodide的WASM沙箱限制。命令执行实现代码获得了在宿主操作系统运行n8n Docker容器的系统上执行命令的能力。风险确认攻击者可以利用此功能执行任意命令包括但不限于读取敏感文件/etc/passwd,~/.n8n/config、植入后门、进行内网横向移动、加密文件进行勒索等。你应该记录下成功的载荷、n8n的版本号、Pyodide的版本号如果能在代码中获取到以及确切的输出结果。这些信息对于后续分析漏洞影响范围和修复方案至关重要。4. 漏洞利用链的深入分析与拓展仅仅复现命令执行还不够作为一个安全研究者或运维人员我们需要理解漏洞的完整利用链评估其真正的杀伤力。4.1 从代码执行到持久化后门一个简单的ls或id命令证明漏洞存在但真实的攻击会走得更远。假设攻击者已经通过某种方式如钓鱼获取凭证、利用其他漏洞获得了在n8n中编辑工作流的权限他可以利用CVE-2025-68668做以下事情信息收集执行ifconfig、netstat -tulnp、env、cat /proc/version等命令摸清服务器环境、网络配置、运行的服务。窃取敏感数据n8n通常用于集成各种API和数据库其配置中可能存储了大量密钥、令牌和数据库凭证。攻击者可以编写Python代码遍历服务器文件系统寻找包含key、secret、password、.env、.n8n等关键词的文件并外传。植入持久化后门直接在服务器上写入一个Web Shell如一个简单的PHP或Python HTTP服务或者创建一个反向Shell连接到攻击者控制的服务器。例如通过Python代码下载并执行一个静态链接的二进制后门或者利用n8n本身的工作流调度功能创建一个定时执行恶意命令的“计划任务”。横向移动如果n8n服务器在内网中攻击者可以利用它作为跳板扫描和攻击内网中的其他机器。他们可以通过Python脚本调用nmap、sshpass等工具如果服务器上安装了的话或者直接使用Python的socket、paramiko如果沙箱允许导入等库进行内网渗透。4.2 利用场景与权限边界探讨这个漏洞的利用有一个关键前提攻击者需要具备在目标n8n实例上创建或修改工作流并能执行包含Code节点的权限。这通常对应以下场景内部威胁心怀不满或有恶意的员工其账号本身就有编辑工作流的权限。供应链攻击如果n8n被集成为一个公共服务的一部分且该服务允许用户自定义工作流例如某些低代码平台那么任意注册用户都可能成为潜在攻击者。组合利用攻击者首先通过其他漏洞例如n8n的另一个未授权访问漏洞、弱口令、或者针对管理员的社会工程学攻击获得高级权限然后利用此漏洞进行深度利用。权限提升如果一个低权限用户只能编辑某个特定工作流但该工作流恰好包含一个Code节点且输入参数部分存在注入点虽然可能性较低也可能构成攻击路径。因此在评估风险时不能孤立地看这个漏洞而要将其放在整个应用的安全上下文中。一个严格遵循最小权限原则、对工作流编辑进行严格审计和审批的n8n部署受此漏洞的影响会小很多。反之一个允许所有用户自由创建和执行任意工作流的公开n8n实例风险则是灾难性的。4.3 漏洞的变种与绕过思路在修复补丁发布后攻击者可能会寻找新的绕过方法。可能的思路包括寻找未禁用的危险函数如果补丁只是黑名单禁用了os和subprocess那么攻击者可能会寻找其他可以执行命令的模块或函数例如pty、commandsPython 2、或者通过ctypes模块直接调用libc的system函数如果Pyodide环境编译时包含了这些库。利用JavaScript桥接Pyodide的js对象是通往JavaScript世界的桥梁。如果Node.js宿主环境中的某些全局对象或函数可以通过js访问并且这些函数能导致命令执行例如不小心暴露了require(child_process).exec那么这将成为新的逃逸路径。文件系统操作即使不能直接执行命令如果能进行任意文件读写攻击者也可以造成严重破坏例如覆盖关键配置文件、写入计划任务crontab、或者写入SSH公钥等。内存破坏或WASM漏洞理论上如果Pyodide的WASM运行时或CPython编译到WASM的部分存在内存安全漏洞也可能导致沙箱被彻底打破。但这属于更高阶的攻击方式。5. 漏洞修复方案与加固建议复现和研究漏洞的最终目的是为了修复和防御。针对CVE-2025-68668我们可以从官方升级、配置加固、架构优化三个层面来应对。5.1 官方补丁与版本升级这是最直接、最推荐的解决方案。n8n官方在获悉漏洞后会发布安全修复版本。确定修复版本关注n8n的官方GitHub仓库的安全公告或发布页面。通常CVE编号会关联到具体的修复提交或版本号。例如修复可能包含在n8n1.71.1或更高的版本中。升级n8nDocker用户更新你的Docker镜像标签到最新稳定版。docker pull n8nio/n8n:latest # 或指定一个已知修复的版本 docker pull n8nio/n8n:1.71.1然后重新创建容器。npm/docker-compose/裸机安装用户按照官方升级指南进行操作通常涉及更新软件包或替换二进制文件。验证修复升级后重复上述复现步骤。使用之前成功的攻击载荷进行测试此时应该看到命令执行失败并返回明确的权限错误或模块未找到错误。这是验证修复是否生效的最佳方式。5.2 运行时安全加固配置即使打了补丁从深度防御的角度我们也应该对n8n的运行环境进行加固。严格遵循最小权限原则运行用户绝不要以root用户运行n8n。在Docker中使用-u参数指定非root用户如node。在宿主机上创建一个专用低权限用户来运行n8n服务。文件系统权限将n8n的数据目录、配置目录的权限设置为仅运行用户可读写。使用Docker卷或宿主机目录挂载时注意所有权和权限。容器化隔离使用Docker或Podman等容器技术部署n8n可以利用内核的命名空间、cgroups等机制进行资源隔离。确保容器以只读根文件系统--read-only运行并以非特权模式运行。网络隔离将n8n部署在内网严格限制其出站和入站连接。如果n8n需要访问外部API通过白名单机制控制出站流量。使用反向代理如Nginx对外暴露并配置严格的WAF规则尽管对这类漏洞可能效果有限但能防御其他常见Web攻击。审计与监控工作流审计定期审查n8n中的工作流特别是那些包含Code节点的工作流。关注是否有未知或可疑的代码被添加。系统监控在运行n8n的服务器上部署HIDS主机入侵检测系统监控异常进程创建、可疑命令执行和文件系统改动。集中收集和分析n8n的应用日志。访问控制强化认证启用并强制使用多因素认证MFA来保护n8n的管理员和用户账户。权限细分仔细规划n8n内的用户角色和权限。除非绝对必要不要给普通用户“可以编辑和执行任何工作流”的权限。考虑使用工作流版本控制和审批流程。5.3 针对代码节点的安全策略对于必须使用Code节点的场景可以考虑以下主动防御措施代码审查与静态分析如果团队规模允许建立对生产环境工作流中Code节点代码的审查流程。可以尝试集成简单的静态分析工具扫描代码中是否包含明显危险的字符串如import os,subprocess,eval,exec等但这只是一种辅助手段很容易被绕过。使用替代方案评估是否真的需要内联Python代码。许多逻辑可以通过串联多个内置节点如Function节点、IF节点、HTTP Request节点来实现。n8n的Function节点JavaScript在沙箱安全性上相对更好一些运行在VM2等沙箱中但也不是绝对安全同样需要关注相关漏洞。沙箱强化高级对于有深厚技术能力的团队可以考虑定制Pyodide的构建移除或禁用所有不必要的、潜在危险的Python模块和C扩展。或者探索使用更严格的沙箱技术如gVisor、Firecracker microVM来隔离整个n8n进程。但这会带来显著的复杂性和性能开销。6. 排查与应急响应指南如果你怀疑自己的n8n实例已经遭受利用此漏洞的攻击或者在进行安全评估时发现了可疑迹象可以按照以下步骤进行排查和应急响应。6.1 入侵迹象识别以下是一些可能表明n8n实例被利用的迹象异常工作流管理界面中出现名称奇怪、描述不清、或包含大量Code节点的新工作流。特别是那些被设置为“激活”状态定期自动执行的工作流。未知的代码内容检查现有工作流中的Code节点查看Python代码部分是否被篡改插入了可疑的import语句、系统命令调用os.system,subprocess.call、网络连接代码socket、requests或文件操作代码。系统资源异常服务器出现异常的CPU、内存或网络流量飙升尤其是在n8n进程相关的时段。未知进程或连接在服务器上使用ps aux | grep n8n或netstat -tulnp查看是否有n8n进程发起的异常子进程或对外部可疑IP地址的连接。文件系统改动在n8n数据目录、系统临时目录或Web根目录下发现陌生的可执行文件、脚本文件或Webshell文件。安全日志告警如果部署了HIDS或监控系统可能会收到关于异常命令执行、敏感文件读取或反弹Shell连接的告警。6.2 应急响应步骤一旦确认或高度怀疑存在入侵应立即采取以下措施立即隔离网络隔离在防火墙上阻断该服务器对所有非必要IP的访问特别是出站连接防止数据外泄或攻击者维持控制。服务下线停止n8n的Docker容器或服务进程。注意如果为了取证在停止前可能需要先创建内存转储。取证与调查备份现场对整个n8n的数据目录通常是~/.n8n或Docker卷挂载点、Docker容器如果使用进行完整备份。备份系统日志/var/log/、命令历史.bash_history等。分析工作流在隔离环境中仔细检查备份出来的n8n数据库通常是SQLite或JSON文件查找所有被修改或新增的、包含Code节点的工作流。提取其中的恶意代码。分析日志检查n8n的应用日志寻找代码执行相关的错误信息或成功记录。检查系统日志寻找与n8n进程UID相关的可疑活动。排查持久化检查系统的计划任务crontab、服务systemd、启动项、SSH授权密钥等位置看攻击者是否植入了后门。清除与恢复清除后门根据取证结果删除所有恶意文件、进程、计划任务和账户。重置凭证重置n8n数据库中的所有用户密码、所有通过n8n集成的第三方服务的API密钥、令牌和密码。恢复服务在完成漏洞修复前切勿恢复服务首先将n8n升级到已修复CVE-2025-68668的安全版本。然后从干净的备份确信入侵发生前的备份中恢复工作流数据。如果备份不可用或不可信则需要手动审查和清理每一个工作流。最后在新的、加固过的环境中重新部署服务。复盘与加固分析入侵根本原因是弱口令、其他漏洞导致权限获取还是内部威胁修复安全短板并实施前面章节提到的加固建议尤其是强化认证、权限控制和监控。6.3 漏洞修复验证清单在完成修复和加固后建议执行一个简单的验证清单确保漏洞已被有效封堵检查项操作方法预期结果版本确认登录n8n查看设置中的版本号。版本号应高于修复版本如1.71.1。基础漏洞复现创建一个新的Python Code节点尝试执行包含import os; os.system(‘id’)的代码。应执行失败并返回模块导入错误或安全错误而非命令执行结果。模块导入测试在Code节点中尝试导入subprocess,socket,ctypes,importlib等敏感模块。应返回ModuleNotFoundError或明确的访问拒绝错误。文件读写尝试尝试使用open(‘/etc/passwd’, ‘r’).read()读取系统文件。应因权限不足或沙箱限制而失败。权限检查检查运行n8n进程的系统用户如 ps auxgrep n8n。网络隔离从n8n服务器尝试访问一个外部地址如curl https://ifconfig.me。应根据网络策略最好无法访问或访问被限制。通过以上系统的复现、分析和加固我们不仅理解了CVE-2025-68668这个特定漏洞的原理与危害更重要的是建立起了一套针对n8n这类可编程自动化工具的安全评估与防护思路。安全是一个持续的过程尤其是在使用如此灵活强大的工具时时刻保持警惕遵循最小权限和深度防御原则才能让自动化真正为业务赋能而非带来风险。