A Brief Note About Security
With all the major topics of accessing the operating system from within PHP addressed, let me take a moment to discuss a number of functions and important pieces of information related to security and these functions. Because many of these functions are low-level operating-system functions, they have the power to be incredibly useful as well as incredibly dangerous. It is absolutely critical that any and all external commands executed from within a PHP script are done with security of your application foremost in your mind as a developer. This holds true not only for calling external commands, but anytime your scripts access operating-system level commands from within PHP.
When considering the security of your application and PHP, there is much too much to discuss in a brief section. However, if you were to sum up everything, the single most important piece of advice is simple: Never trust external data from an unknown source. One of the single biggest mistakes that can be made is the execution of an external command based on user input. For example, consider the following brief PHP script in Listing 22.20:
Listing 22.20. Insecurely Calling an External Command
<?php $filename = $_GET['filename']; echo `cat $filename`; ?>
Although a very simple script (perhaps a helper script for a bigger application), this script is also a security risk. Because no validation is done against the user-submitted variable $filename, users are free to modify this variable in any way they see fit. For instance, the user could set $filename to /etc/passwd to get a list of accounts (and perhaps encrypted passwords) on the system.
Not only can a malicious user use the script in Listing 22.20 to display an unintended file, but a clever user could even use this script to execute arbitrary commands on your Web server! In Unix platforms, multiple commands can be executed in a single line by separating them with a semicolon character.
By doing so, although completely unintended, has turned your PHP script into a script that attempts to remove every file on the file system!
Although the best protection against this behavior is to be aware of such potential security concerns (the PHP manual does a fair job of warning you when a particular function is potentially dangerous), a number of functions can help you ensure that your scripts cannot be taken advantage of. Two of these functions that are noteworthy are the escapeshellcmd() and escapeshellarg() functions. The syntax for these functions follows:
These functions, when executed, automatically escape any potentially dangerous characters within a string to ensure that their literal meaning is passed to any function that externally executes a program from PHP. For instance, the escapeshellcmd() function accepts a single parameter, $command, representing a shell command to execute and returns the same command with all potentially dangerous characters (such as a semicolon) escaped. Thus the string
;rm -Rf /*
\;rm -Rf /\*
preventing any malicious command execution. Likewise, the escapeshellarg() function can be used to remove any potentially dangerous characters from input designed to be used as a command-line parameter to an externally executed command. Unlike the escapeshellcmd() function, the escapeshellarg() function will quote each individual command-line parameter and escape any quotes contained within the string. Thus, the string
--option=;rm -Rf /* --mystring='foo bar'
'--option=;rm -Rf /* --mystring='\''foo bar'\'''
Preserving the literal meaning of the arguments while preventing any malicious attempts to hack the script.
In the end, these two functions only scratch the surface of potential security risks when you use not only the functions discussed in this chapter, but throughout this book. It is strongly recommended that the PHP manual be consulted on questionable functions to ensure proper usage to keep your scripts as secure as possible.