When user input takes over your entire Linux server.
Command injection is a vulnerability where an application executes arbitrary Operating System (OS) commands provided by a user. It happens when an application passes unsafe user-supplied data (like forms, cookies, or HTTP headers) directly into a system shell using functions like `system()`, `exec()`, or `os.system()`.
This is arguably worse than SQL Injection, because gaining a shell on the server allows the attacker to pivot deeper into your infrastructure.
If you must execute a system command, NEVER use a function that spawns a full shell (`sh -c`). Instead, execute the binary directly and pass the user input strictly as an argument array, preventing shell metacharacters (like `&&`, `;`, `|`) from being evaluated.
import subprocess
# VULNERABLE: Spawns a shell. A user can input "8.8.8.8 ; rm -rf /"
def ping_server(ip_address):
# shell=True is the root of all evil
subprocess.run(f"ping -c 1 {ip_address}", shell=True)
# SECURE: Direct execution via arg array.
def ping_server(ip_address):
# shell=False (default). The OS treats the entire string as one argument.
# The "rm -rf" will literally be passed to 'ping', which will just fail.
subprocess.run(["ping", "-c", "1", ip_address])
An image processing app takes a user's uploaded filename and runs `imagemagick convert
Why is executing commands as an argument array `['ping', ip]` safe, while executing a concatenated string `ping + ip` via a shell dangerous?