I’m writing a setup/installer script for my application, basically just a nice front end to the configuration file. One of the configuration variables is the executable path for mysql. After the user has typed it in (for example: /path/to/mysql-5.0/bin/mysql or just mysql if it is in their system PATH), I want to verify that it is correct. My initial reaction would be to try running it with "--version" to see what comes back. However, I quickly realised this would lead to me writing this line of code:
shell_exec($somethingAUserHasEntered . " --version");
…which is obviously a Very Bad Thing. Now, this is a setup script which is designed for trusted users only, and ones which probably already have relatively high level access to the system, but still I don’t think the above solution is something I want to write.
Is there a better way to verify the executable path? Perhaps one which doesn’t expose a massive security hole?
Running arbitrary user commands is like running queries based on user input… Escaping is the key.
First, validate if it is an executable using
is_executable().PHP exposes two functions for this:
escapeshellarg()andescapeshellcmd().escapeshellarg()adds single quotes around a string and quotes/escapes any existing single quotes allowing you to pass a string directly to a shell function and having it be treated as a single safe argument.escapeshellcmd()escapes any characters in a string that might be used to trick a shell command into executing arbitrary commands.This should limit the amount of risk.
After all, doing
rm --versionisn’t very harmful, and"rm -rf / &&" --versionwill get you anywhere very fast.EDIT: Since you mentioned
PATH… Here is a quick function to validate if the file is an executable according toPATHrules: