Of course, there's nothing particularly insecure about this example because the system command has been hardcoded as an exec() parameter. However, let's return to the earlier scenario where a user was allowed to key in a Social Security Number, which was subsequently provided to a Ruby script. The user would presumably provide this input via a web form, with the SSN passed via the $_POST array. Coded in an insecure fashion, the script might look like this:

Securing Your Scripts

Fortunately, several options are at your disposal for preventing such unintended consequences. The easiest solution involves using the escapeshellarg() and escapeshellcmd() functions to convert the user-supplied data into a safe format. The escapeshellarg() function will delimit the data with single quotes, as well as any single quotes already found in the data, thereby causing the data to be treated as a single argument. Therefore, the above malicious input would be converted to this:

'123-45-6789 ; cat /etc/passwd'

Once delimited, the PHP script will now produce the following output:

The SSN is 123-45-6789 ; cat /etc/passwd

The escapeshellcmd() function will escape any characters that could be used to trigger a system command. If applied to the above user-supplied data, the string will be converted to the following before being passed to the Ruby script:

123-45-6789 \; cat /etc/passwd

With the semi-colon escaped, the ensuing command can no longer be interpreted by the operating system.

Where to From Here?

Creating web-based applications that integrate tightly with the underlying operating system is pretty easy to do. However, you must be vigilant to avoid the serious security issues that can arise due to unchecked user input. Fortunately, PHP's native functionality makes it easy to vet user input in a way that greatly reduces the likelihood of stolen or damaged server data.