Выполнение произвольных пользовательских команд похоже на выполнение запросов на основе пользовательского ввода ... Экранирование - это ключ.
Сначала проверьте, если это исполняемый файл, используя is_executable()
.
PHP предоставляет две функции для этого: escapeshellarg()
и escapeshellcmd()
.
escapeshellarg()
добавляет одинарные кавычки вокруг строки и заключает в кавычки / экранирует любые существующие одинарные кавычки, позволяя передавать строку непосредственно в функцию оболочки и обрабатывать ее как один безопасный аргумент.
escapeshellcmd()
экранирует любые символы в строке, которые могут использоваться, чтобы обмануть команду оболочки при выполнении произвольных команд.
Это должно ограничить количество риска.
if(is_executable($somethingAUserHasEntered)) {
shell_exec(escapeshellarg($somethingAUserHasEntered) . " --version");
}
В конце концов, выполнение rm --version
не очень вредно, и "rm -rf / &&" --version
очень быстро доставит вас куда угодно.
РЕДАКТИРОВАТЬ: Поскольку вы упомянули PATH
... Вот быстрая функция для проверки, если файл является исполняемым в соответствии с PATH
правилами:
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;
}