I'm writing a setup/installer script for my application, ba开发者_JAVA百科sically 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()
and escapeshellcmd()
.
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.
if(is_executable($somethingAUserHasEntered)) {
shell_exec(escapeshellarg($somethingAUserHasEntered) . " --version");
}
After all, doing rm --version
isn't very harmful, and "rm -rf / &&" --version
will get you anywhere very fast.
EDIT: Since you mentioned PATH
... Here is a quick function to validate if the file is an executable according to PATH
rules:
function is_exec($file) {
if(is_executable($file)) return true;
if(realpath($file) == $file) return false; // Absolute Path
$paths = explode(PATH_SEPARATOR, $_ENV['PATH']);
foreach($paths as $path) {
// Make sure it has a trailing slash
$path = rtrim($path, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR;
if(is_executable($path . $file)) return true;
}
return false;
}
You could try a simple file_exists
call to determine if something exists at that location, along with an is_executable
to confirm that it's something you can run.
have you looked at is_dir()
or is_link()
or is_file()
or is_readable()
Hope these help.
system('which '.escapeshellarg($input))
will give you the absolute path to the executable, regardless if it's just the name or an absolute path.
精彩评论