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 exec()
, 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 withescapeshellarg()
.
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 withmysql_real_escape_string()
(or 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.