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();
}
工程与系统安全加固清单
- ✓升级到受支持且包含
CVE-2024-27980和CVE-2024-36138修复的 Node.js 版本。 - ✓避免使用外部数据启动批处理脚本;优先直接调用可执行文件并验证参数。
- ✓若必须使用 shell,应把 shell: true 视为命令执行,并实施严格验证与授权。
- ✓添加 Windows 回归测试,覆盖
spawn()、spawnSync()和批处理扩展名,并验证 EINVAL 安全拒绝。