Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

🏠 Back to Blog

Command Injection Prevention

Avoid system command functions

Prefer built-in language functions over system command execution. For example, in PHP, use fsockopen() to test connectivity instead of executing ping via system().

When system commands are unavoidable:

  • Never pass raw user input directly to them
  • Validate and sanitize on the back-end before use
  • Minimize their use — only when no built-in alternative exists

Front-end validation alone is insufficient; it is trivially bypassed by sending raw HTTP requests.

Input validation

Validate that input matches its expected format before processing. Implement on both front-end and back-end.

PHP — built-in IP filter:

if (filter_var($_GET['ip'], FILTER_VALIDATE_IP)) {
    // call function
} else {
    // deny request
}

PHP — custom regex:

preg_match('/^([0-9]{1,3}\.){3}[0-9]{1,3}$/', $_GET['ip'])

NodeJS — regex:

if (/^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(...)$/.test(ip)) {
    // call function
} else {
    // deny request
}

NodeJS — library: is-ip (npm install is-ip, use isIp(ip))

PHP’s filter_var has built-in validators for emails, URLs, IPs, and other standard formats. Consult the docs for .NET, Java, and other platforms for their equivalents.

Input sanitization

Sanitize after validation: remove all characters not required for the expected format. Allowlists (“allow only known good”) are stronger than blacklists (“block known bad”).

PHP — allowlist regex:

$ip = preg_replace('/[^A-Za-z0-9.]/', '', $_GET['ip']);

JavaScript:

var ip = ip.replace(/[^A-Za-z0-9.]/g, '');

NodeJS — DOMPurify:

import DOMPurify from 'dompurify';
var ip = DOMPurify.sanitize(ip);

For inputs that must allow special characters (e.g., free-text comments), use escapeshellcmd (PHP) or escape() (Node) to escape them — though escaping is weaker than allowlist sanitization and can often be bypassed.

Server configuration

Reduce blast radius if the server is compromised:

  • Enable the web server’s built-in WAF (e.g., Apache mod_security) plus an external WAF (Cloudflare, Fortinet, Imperva)
  • Run the web server as a low-privilege user (Principle of Least Privilege — e.g., www-data)
  • Disable dangerous PHP functions: disable_functions=system,exec,shell_exec,passthru,...
  • Restrict web app filesystem scope: open_basedir = '/var/www/html'
  • Reject double-encoded requests and non-ASCII characters in URLs
  • Avoid sensitive or outdated modules (e.g., PHP CGI)

Secure configuration complements secure coding — neither alone is sufficient. Pair both with ongoing penetration testing, since any single mistake in a large codebase can reintroduce a vulnerability.