Full Report
The vulnerability is a known issue that was originally processed over 10 years ago. However, it's such a common mistake that languages keep making the mistake again and again. When executing system commands via a subshell, it's important escape these characters. Otherwise, command injection can be used to control the system. Most languages have this feature and it works well. In order to prevent command injection, the malicious inputs are commonly escaped. Additionally, the inputs can be processed with a unique argument context, preventing the meaningful bash metacharacters from doing anything on Linux and Mac. On Windows, the process is entirely different though. When executing a .bat (batch) file on Windows, the OS will automatically do C:\Windows\System32\cmd.exe .\test.bat within CreateProcess. Most languages want to escape the input being used in order to prevent command injection. However is this escaping done? Using backslashes! However, unlike Linux, Windows doesn't process these as an escape - it uses ^. So, \" is insufficient. This leads to shell metacharacters being able to break out of the escaping! For instance, using "&calc.exe as the input for a spawn in NodeJS will execute calc. This leads to command injection on Windows systems whenever a batch file is used and inputs can be provided to it. The obvious way to fix this would be using a caret(^) instead of backslash. However, the command prompt will expand variables inline before other parsing. So, it's possible to use substring of ENV variables to add in your own quotes once again, which is bad. How do we actually fix this then? As a developer, fixing this issue is super tricky because of the issue mentioned above. It involves disabling the automatic escaping then replacing a bunch of dangerous characters by hand. As a runtime maintainer, no extra info was added but was something that just needs to be fixed... weird. Overall, a weird vulnerability in the interoperability of different systems. The bug has been around for a while! I enjoyed the debunking of the obvious fix in my mind as well.
Analysis Summary
# Vulnerability: BatBadBut - Command Injection via Windows Batch File Execution
## CVE Details
- **CVE ID**: [CVE-2024-27980] (Node.js), [CVE-2024-1874] (PHP), [CVE-2024-22423] (Python), [CVE-2024-24576] (Rust), [CVE-2024-3566] (Haskell), [CVE-2024-123335] (CERT/CC umbrella ID)
- **CVSS Score**: 7.8 to 9.6 (High/Critical) — *Scores vary by specific language implementation*
- **CWE**: CWE-78 (OS Command Injection)
## Affected Systems
- **Products**: Multiple programming language runtimes including Node.js, PHP, Python, Ruby, Go, Rust, Erlang, and Haskell.
- **Versions**: Various versions; specifically those that implement command execution wrappers for Windows without proper shell-character escaping for batch files.
- **Configurations**:
- Applications running on **Windows OS**.
- Applications that execute commands where the file extension is not specified OR is explicitly `.bat` or `.cmd`.
- Applications that pass user-controlled input as arguments to these commands.
## Vulnerability Description
The "BatBadBut" vulnerability arises from the way the Windows `CreateProcess` function handles batch files. When a `.bat` or `.cmd` file is executed, Windows implicitly spawns `cmd.exe`.
While most programming languages attempt to escape command arguments to prevent injection, they typically use backslashes (`\`) for escaping (the standard for `.exe` files). However, `cmd.exe` does not recognize backslashes as escape characters; it uses carets (`^`). Because of this discrepancy, malicious users can provide inputs containing shell metacharacters (like `"` or `&`) to break out of the intended argument context and execute arbitrary system commands.
## Exploitation
- **Status**: PoC available; widely documented by security researchers.
- **Complexity**: Low to Medium (requires finding an application that passes input to a batch file).
- **Attack Vector**: Network (if the application accepts remote input for command arguments).
## Impact
- **Confidentiality**: High (Attacker can read sensitive system files).
- **Integrity**: High (Attacker can modify or delete files and system configurations).
- **Availability**: High (Attacker can shut down services or cause system crashes).
## Remediation
### Patches
- **Node.js**: Update to v18.20.2, v20.12.2, or v21.7.3.
- **Rust**: Update to 1.77.2.
- **PHP**: Update to 8.1.28, 8.2.18, or 8.3.6.
- **Other Languages**: Check specific vendor advisories for Go, Python, and Ruby.
### Workarounds
- **Explicit Extensions**: Always specify the `.exe` extension when calling executable files to prevent the OS from accidentally finding and executing a `.bat` file with the same name.
- **Move Batch Files**: Move batch files to directories that are not in the application's search path or the system `PATH`.
- **Manual Sanitization**: If executing a batch file is mandatory, developers must manually escape or reject dangerous characters (like quotes, carets, and ampersands) before passing them to the runtime.
## Detection
- **Indicators of Compromise**: Monitor process logs for `cmd.exe` being spawned with suspicious arguments (e.g., `& calc.exe`, `& powershell.exe`, or multiple nested quotes).
- **Detection Methods**: Use Static Analysis Security Testing (SAST) tools to search for `spawn`, `exec`, or `system` calls that process user input without extension validation on Windows platforms.
## References
- **CERT/CC Advisory**: [https://kb.cert.org/vuls/id/123335](https://kb.cert.org/vuls/id/123335)
- **Original Research**: [https://flatt.tech/research/posts/batbadbut-you-cant-securely-execute-commands-on-windows/](https://flatt.tech/research/posts/batbadbut-you-cant-securely-execute-commands-on-windows/)