Cross-site scripting flaws happen when you display unfiltered, unescaped malicious content to a user’s browser. Command injection flaws happen when you pass unfiltered, unescaped malicious commands to an external process or database. To prevent command injection flaws, in addition to validating input, always escape user input before passing it to an external process or database.
If you’re passing user input to a shell (via a command like
system(), or the backtick operator), first, ask yourself if you really need to. Most file operations can be performed with native PHP functions. If you absolutely, positively need to run an external program whose name or arguments come from untrusted input, escape program names with
escapeshellcmd() and arguments with
Before executing an external program or opening an external file, you should also canonicalize its pathname with
realpath(). This expands all symbolic links, translates
. (current directory)
.. (parent directory), and removes duplicate directory separators. Once a pathname is canonicalized you can test it to make sure it meets certain criteria, like being beneath the web server document root or in a user’s home directory.
If you’re passing user input to a SQL query, escape the input with
addslashes()before putting it into the query. If you’re using MySQL, escape strings with
mysql_escape_string() for PHP versions before 4.3.0). If you’re using the PEAR DB database abstraction layer, you can use the DB::quote() method or use a query placeholder like
?, which automatically escapes the value that replaces the placeholder.