漏洞介绍

通过字符串格式化和异常处理,攻击者可以绕过 n8n 的 Python 任务执行器沙箱限制,在底层操作系统中运行任意的、不受限制的 Python 代码。该漏洞可通过“代码块”功能被拥有基本权限的已验证用户利用,并可能导致运行在“内部”执行模式下的 n8n 实例被完全接管。如果实例运行在“外部”执行模式下(例如,使用 n8n 的官方 Docker 镜像),任意代码执行将发生在一个 Sidecar 容器内,而非主节点,这大大降低了漏洞的影响。

漏洞影响

CVSS评分:8.5(高)

版本:n8n < 1.123.14,2.0.0 <= n8n < 2.3.5,2.4.0 <= n8n < 2.4.2

影响:

"内部"执行模式:全面接管n8n实例

"外部"执行模式(Docker Sidecar):限制在Sidecar容器内,影响较小

漏洞分析

1.用户输入

用户在n8n工作流界面的Python代码节点输入:

2.后端验证绕过

validate() 检查用户代码

通过BLOCKED_ATTRIBUTES检查属性名是否含有违法属性

但是在BLOCKED_ATTRIBUTES列表中没有'obj',这就导致用户输入的代码中不会检测'obj'属性

这里只检查直接的__import__()调用,不会检查通过字符串格式化执行的__import__,这就导致了用户输入的代码存在这个也不会爆:

此时,用户的代码就过了安全检测

3.漏洞触发

这里就是整个漏洞最终之地

该段代码将用户的输入进行包装

这里将包装好的字符串代码转换为Python字节码对象:

wrapped_code:包含 _user_function() 定义的字符串

EXECUTOR_ALL_ITEMS_FILENAME:一个常量(通常是"<all_items>"),作为代码的“文件名”出现在错误信息中

"exec":编译模式,表示编译的是可执行代码块(而非单个表达式)

这个 globals 字典是沙箱安全机制的核心,它定义了用户代码能访问和不能访问的一切。它通过以下方式构建了一个受控的执行环境:

_filter_builtins:调用该字典进行过滤

_items 和 _query:只传递数据,不传递引用

自定义的 print 函数:

确保所有print参数都能安全地通过multiprocessing管道和WebSocket传输

输出被收集到print_args列表,可以:返回给前端界面显示,进行安全审查和日志记录,限制输出数量

在受限制的globals中执行代码

由于对于默认过滤字典攻击者可以通过e.obj绕过该过滤,从而使得用户可以得到未过滤的__builtins__,__import__,使得_filter_builtins无用了

执行完成后,从globals中提取用户代码的输出:

EXECUTOR_USER_OUTPUT_KEY 是 _user_output(前面包装时赋值的变量名)

现在,漏洞在后端的调用链变得清晰明了:

通过用户输入,task_analyzer.py文件未过滤obj,导致安全验证被绕过,然后到task_executor.py文件漏洞触发点的过滤也被e.obj绕过,最终攻击者使用e.obj进行属性访问导致RCE

官方修复图片.png

对constants.py黑名单添加obj

参考

https://github.com/n8n-io/n8n/commit/b73a4283cb14e0f27ce19692326f362c7bf3da02

https://www.venustech.com.cn/new_type/aqtg/20260119/29101.html

https://github.com/n8n-io/n8n/blob/n8n%402.2.5/packages/%40n8n/task-runner-python/src/task_executor.py

https://nvd.nist.gov/vuln/detail/CVE-2026-0863

标签: none

添加新评论