CVE-2024-27980 / BatBadBut Zero-Day

CVE-2024-27980: Node.js Windows Batch File Argument Injection (BatBadBut) Teardown

How implicit cmd.exe invocation during child_process.spawn() on Windows allowed arbitrary command execution when invoking .bat or .cmd files.

💡 Plain English Explainer (ELI5)

Imagine you tell a helper: 'Go tell the computer to run the script `build.bat` with the parameter `file.txt`'. On Windows, the helper doesn't run the file directly—he passes it to a command prompt assistant. If the parameter is `file.txt & calc.exe`, the command prompt sees the `&` symbol and immediately launches the calculator program with full access.

Core Concepts & Subsystem Terms

BatBadBut Vulnerability
A multi-language vulnerability (affecting Node.js, Python, Rust, PHP) on Windows when spawning batch files.
child_process.spawn()
The Node.js method to launch external OS processes asynchronously.
CreateProcessW
The Windows Win32 API used to create processes, which does not execute `.bat` files directly without wrapping them in `cmd.exe`.
Command Separator (&, |)
Special shell characters that instruct the command interpreter to execute a secondary independent command.

Step-by-Step Exploit Mechanics

Step 1

1. Application Launches Batch File

A Node.js backend on Windows calls child_process.spawn('setup.bat', [userInput]).

Step 2

2. Crafted Parameter Injection

The attacker supplies input containing quotes and command chaining operators: test" & calc.exe.

Step 3

3. Implicit cmd.exe Invocation

Windows launches cmd.exe /c setup.bat "test" & calc.exe.

Step 4

4. Arbitrary Remote Code Execution

The shell interprets the & symbol, executing the attacker's arbitrary command.

Source Code: Fatal Flaw vs. High-Level Fix

Delivered in clean, readable high-level source code (no raw assembly or binary diffs).

UNPATCHED FLAW
// VULNERABLE: lib/child_process.js before patch
function spawn(file, args, options) {
    // ROOT CAUSE:
    // On Windows, if 'file' ends in .bat or .cmd, CreateProcess cannot execute it directly.
    // Node.js spawned 'cmd.exe /d /s /c' without properly escaping quotes inside args!
    if (process.platform === 'win32' && /\.(bat|cmd)$/i.test(file)) {
        return spawn('cmd.exe', ['/d', '/s', '/c', file, ...args], options);
    }
}
HARDENED PATCH
// SECURE: lib/child_process.js patch
function spawn(file, args, options) {
    if (process.platform === 'win32' && /\.(bat|cmd)$/i.test(file)) {
        // 1. By default, refuse to spawn batch files without explicit shell acknowledgment
        if (!options.shell) {
            const err = new Error(`EINVAL: Spawning batch files on Windows requires explicit options.shell`);
            err.code = 'EINVAL';
            throw err;
        }
        
        // 2. Perform rigorous Windows command argument escaping
        args = args.map(arg => sanitizeBatchArg(arg));
    }
}

Engineering & System Hardening Checklist

← Browse Full Security Directory Explore All Source Teardowns →