views:

31

answers:

3

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?

+1  A: 

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.

VoteyDisciple
that won't work when the executable is in the PATH.
nickf
A: 

have you looked at is_dir() or is_link() or is_file() or is_readable()

Hope these help.

RobertPitt
I'm pretty sure the guy with 45k reputation points is aware of basic PHP file functions...
Matchu
@Matchu lol - i think rep is more of a measure of your spare time than anything else. :-p. @Robert thanks, I have seen these, but they don't help when the file is in the system PATH.
nickf
+2  A: 

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;
}
Andrew Moore
+1 Personally I woudl not even prompt the user, but would just step along the path looking for the .exe Yes, I suppose that they _could_ rename mysql, but how realistic is that? In the worst case you could output "Sorry, I can't find mysql(.exe) on the path <path value>. Is it installed? Perhaps you renamed it?"
Mawg