FlawOpen

flawopen.com/Teardowns/cve-2024-27980-nodejs-windows-batch-injection

● CVE-2024-27980 · CVSS 8.1 · 高危
安全研究 · FlawOpen

CVE-2024-27980:Node.js Windows 命令注入

在 Windows 上,即使未启用 shell,spawn() 和 spawnSync() 执行批处理文件时也可能遭遇命令注入。

💡 通俗易懂的原理解析 (ELI5)

想象程序把参数交给批处理文件,但 Windows 必须通过命令解释器运行它。解释器可能把参数当作命令语法。Node.js 的修复是拒绝直接启动批处理文件,而不是猜测如何安全转义每个参数。

核心概念与专有名词

child_process.spawn()
Node.js 异步 API,使用可执行文件和参数列表启动进程。
批处理文件
由 Windows shell 解释的 .bat 或 .cmd 文件,并非使用统一 argv 解析的普通可执行文件。
Shell 元字符
含义由命令解释器决定、可能改变命令结构的字符。
EINVAL
Node.js 用于拒绝不安全直接启动批处理文件的错误代码。

框架映射

  • 本指南所述弱点的 CWE 参考: CWE-77

根本原因剖析 (Root Cause)

在 Windows 上,.bat 和 .cmd 文件由 shell 解释,参数并非总能无歧义地转义。Node.js 安全公告指出,即使未启用 shell,恶意命令行参数也可能通过 child_process.spawn() 和 spawnSync() 注入命令。上游补丁会忽略大小写地识别 .bat 或 .cmd 后缀,并在调用 uv_spawn() 前返回 EINVAL。该补丁没有实现 sanitizeBatchArg(),也不代表 shell: true 是安全的。后续公告指出,对其他批处理文件扩展名的修复不完整(CVE-2024-36138);应安装同时包含两项修复的版本。

攻击执行流程分解

步骤 1

应用调用进程 API

在 Windows 上,应用通过 child_process.spawn() 或 spawnSync() 启动 .bat 或 .cmd 文件,参数可能受外部输入影响。

步骤 2

目标是批处理文件

批处理文件遵循 shell 规则;使用参数数组并不能自动阻止元字符被解释。

步骤 3

Windows 解释参数

易受攻击的行为可能在 shell: false 时仍将参数解释为命令语法。

步骤 4

Node.js 阻止直接启动

补丁在直接启动 .bat/.cmd 时返回 EINVAL。CVE-2024-36138 揭示其他扩展名仍有缺口;请升级到同时包含两项修复的版本。

源代码对比:漏洞与安全实现

存在漏洞的实现
// 安全补丁前 src/process_wrap.cc 中的代码片段
node::Utf8Value file(env->isolate(), file_v);
options.file = *file;

// 文件名传给 uv_spawn() 时没有拒绝批处理文件。
加固后的安全修复
// CVE-2024-27980 上游补丁中的代码片段
node::Utf8Value file(env->isolate(), file_v);
options.file = *file;

// 批处理文件的参数并非总能进行无歧义的转义。
if (IsWindowsBatchFile(options.file))
  err = UV_EINVAL;

if (err == 0) {
  err = uv_spawn(env->event_loop(), &wrap->process_, &options);
  wrap->MarkAsInitialized();
}

工程与系统安全加固清单

参考来源