Shell Injection¶
Shell injection, also called OS command injection, is a security vulnerability in which attacker-controlled data is passed unsanitised to a shell command, allowing the attacker to execute arbitrary commands on the host operating system. It is listed as a critical vulnerability class in the OWASP Top 10: A03: Injection.
The vulnerability arises when PHP passes user input to exec(), system(), passthru(), shell_exec(), or the backtick operator (`` ` ) without properly escaping shell metacharacters. Characters such as ``;, &, |, $(...), and backticks allow an attacker to append or inject additional commands.
If $_GET['file'] contains input.png; rm -rf /, the shell executes both commands.
Mitigation strategies, in order of preference:
Avoid shell execution entirely: use native PHP libraries,
GD,Imagick,ZipArchive, or dedicated extension APIs that do not invoke a shell.Use
proc_open()with an array argument (via the Symfony Process component), which bypasses the shell and passes arguments directly to the OS, making injection impossible.Escape every argument with
escapeshellarg()individually; do not rely onescapeshellcmd()alone.Validate and whitelist input before any shell call: only accept known-good values (e.g., a filename that matches
/^[a-zA-Z0-9._-]+$/).Run the PHP process with the minimum required OS privileges; use a chroot or container to limit blast radius.
<?php
// VULNERABLE: user input passed directly to shell
$file = $_GET['file'] ?? '';
exec('convert ' . $file . ' output.png'); // shell injection risk
// SAFE option 1: escapeshellarg() on each argument
$safeFile = escapeshellarg($file);
exec('convert ' . $safeFile . ' output.png');
// SAFE option 2: Symfony Process (no shell — arguments passed as array)
// $process = new \Symfony\Component\Process\Process(['convert', $file, 'output.png']);
// $process->run();
// if (!$process->isSuccessful()) {
// throw new \RuntimeException($process->getErrorOutput());
// }
// SAFE option 3: native PHP (no shell at all)
$img = new \Imagick($file);
$img->writeImage('output.png');
?>
See also CWE-78: OS Command Injection, Symfony Process component and escapeshellarg() — PHP Manual.
Related : Injection, escapeshellarg(), escapeshellcmd(), exec, Shell Exec, System, Security, Taint Analysis
Related packages : symfony/process