Commit 3c53e05c authored by alaunois's avatar alaunois
Browse files

fix(conf) check path for plugin commands (#11081)



* fix(conf) check path for plugin commands

* fix typo

* fix some warnings

* move escapeshellcmd before exec

* Apply suggestion

* Update www/include/configuration/configObject/command/minHelpCommandFunctions.php

* Update www/include/configuration/configObject/command/minHelpCommandFunctions.php

* Update www/include/configuration/configObject/command/minHelpCommandFunctions.php

* Update www/include/configuration/configObject/command/minHelpCommand.php

Co-authored-by: default avatarKevin Duret <kduret@centreon.com>

Co-authored-by: default avatarKevin Duret <kduret@centreon.com>
parent da8ca7b1
......@@ -34,68 +34,48 @@
*
*/
if (!isset($oreon)) {
if (!isset($centreon)) {
exit();
}
require_once __DIR__ . "/minHelpCommandFunctions.php";
$commandId = filter_var(
$_GET["command_id"] ?? $_POST["command_id"] ?? null,
FILTER_VALIDATE_INT
);
$commandName = filter_var(
$_GET["command_name"] ?? $_POST["command_name"] ?? null,
FILTER_SANITIZE_STRING
);
$commandName = htmlspecialchars($_GET["command_name"] ?? $_POST["command_name"] ?? null);
if ($commandId !== false) {
//Get command information
$sth = $pearDB->prepare('SELECT * FROM `command` WHERE `command_id` = :command_id LIMIT 1');
$sth->bindParam(':command_id', $commandId, PDO::PARAM_INT);
$sth->execute();
$cmd = $sth->fetch();
unset($sth);
$aCmd = explode(" ", $cmd["command_line"]);
$fullLine = $aCmd[0];
$plugin = array_values(preg_grep('/^\-\-plugin\=(\w+)/i', $aCmd))[0];
$mode = array_values(preg_grep('/^\-\-mode\=(\w+)/i', $aCmd))[0];
$aCmd = explode("/", $fullLine);
$resourceInfo = $aCmd[0];
$prepare = $pearDB->prepare(
'SELECT `resource_line` FROM `cfg_resource` WHERE `resource_name` = :resource LIMIT 1'
);
$prepare->bindValue(':resource', $resourceInfo, \PDO::PARAM_STR);
$prepare->execute();
//Match if the first part of the path is a MACRO
if ($resource = $prepare->fetch()) {
$resourcePath = $resource["resource_line"];
unset($aCmd[0]);
$command = rtrim($resourcePath, "/") . "#S#" . implode("#S#", $aCmd);
} else {
$command = $fullLine;
}
$commandLine = getCommandById($pearDB, (int) $commandId) ?? '';
['commandPath' => $commandPath, 'plugin' => $plugin, 'mode' => $mode] = getCommandElements($commandLine);
$command = replaceMacroInCommandPath($pearDB, $commandPath);
} else {
$command = $oreon->optGen["nagios_path_plugins"] . $commandName;
$command = $centreon->optGen["nagios_path_plugins"] . $commandName;
}
// Secure command
$search = ['#S#', '#BS#', '../', "\t"];
$replace = ['/', "\\", '/', ' '];
$command = str_replace($search, $replace, $command);
$command = escapeshellcmd($command);
$tab = explode(' ', $command);
if (realpath($tab[0])) {
$command = realpath($tab[0]) . ' ' . $plugin . ' ' . $mode . ' --help';
} else {
$command = $tab[0] . ' ' . $plugin . ' ' . $mode . ' --help';
// Remove params
$explodedCommand = explode(' ', $command);
$commandPath = realpath($explodedCommand[0]) === false ? $explodedCommand[0] : realpath($explodedCommand[0]);
// Exec command only if located in allowed directories
$msg = "Command not allowed";
if (isCommandInAllowedResources($pearDB, $commandPath)) {
$command = $commandPath . ' ' . ($plugin ?? '') . ' ' . ($mode ?? '') . ' --help';
$command = escapeshellcmd($command);
$stdout = shell_exec($command . " 2>&1");
$msg = str_replace("\n", "<br />", $stdout);
}
$stdout = shell_exec($command . " 2>&1");
$msg = str_replace("\n", "<br />", $stdout);
$attrsText = array("size" => "25");
$form = new HTML_QuickFormCustom('Form', 'post', "?p=" . $p);
$form->addElement('header', 'title', _("Plugin Help"));
......@@ -122,8 +102,6 @@ $form->accept($renderer);
$tpl->assign('form', $renderer->toArray());
$tpl->assign('o', $o);
$tpl->assign('command_line', CentreonUtils::escapeSecure($command, CentreonUtils::ESCAPE_ALL));
if (isset($msg) && $msg) {
$tpl->assign('msg', CentreonUtils::escapeAllExceptSelectedTags($msg, ['br']));
}
$tpl->assign('msg', CentreonUtils::escapeAllExceptSelectedTags($msg, ['br']));
$tpl->display("minHelpCommand.ihtml");
<?php
/*
* Copyright 2005-2022 Centreon
* Centreon is developed by : Julien Mathis and Romain Le Merlus under
* GPL Licence 2.0.
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation ; either version 2 of the License.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, see <http://www.gnu.org/licenses>.
*
* Linking this program statically or dynamically with other modules is making a
* combined work based on this program. Thus, the terms and conditions of the GNU
* General Public License cover the whole combination.
*
* As a special exception, the copyright holders of this program give Centreon
* permission to link this program with independent modules to produce an executable,
* regardless of the license terms of these independent modules, and to copy and
* distribute the resulting executable under terms of Centreon choice, provided that
* Centreon also meet, for each linked independent module, the terms and conditions
* of the license of that module. An independent module is a module which is not
* derived from this program. If you modify this program, you may extend this
* exception to your version of the program, but you are not obliged to do so. If you
* do not wish to do so, delete this exception statement from your version.
*
* For more information : contact@centreon.com
*
*/
declare(strict_types=1);
/**
* @param string $command
* @return bool
*/
function isCommandInAllowedResources(CentreonDB $pearDB, string $command): bool
{
$allowedResources = getAllResources($pearDB);
foreach ($allowedResources as $path) {
if (substr($command, 0, strlen($path)) === $path) {
return true;
}
}
return false;
}
/**
* @param CentreonDB $pearDB
* @param int $commandId
* @return string|null
*/
function getCommandById(CentreonDB $pearDB, int $commandId): ?string
{
$sth = $pearDB->prepare('SELECT command_line FROM `command` WHERE `command_id` = :command_id');
$sth->bindParam(':command_id', $commandId, PDO::PARAM_INT);
$sth->execute();
$command = $sth->fetchColumn();
return $command !== false ? $command : null;
}
/**
* @param CentreonDB $pearDB
* @param string $resourceName
* @return string|null
*/
function getResourcePathByName(CentreonDB $pearDB, string $resourceName): ?string
{
$prepare = $pearDB->prepare(
'SELECT `resource_line` FROM `cfg_resource` WHERE `resource_name` = :resource LIMIT 1'
);
$prepare->bindValue(':resource', $resourceName, \PDO::PARAM_STR);
$prepare->execute();
$resourcePath = $prepare->fetchColumn();
return $resourcePath !== false ? $resourcePath : null;
}
/**
* @param CentreonDB $pearDB
* @return string[]
*/
function getAllResources(CentreonDB $pearDB): array
{
$dbResult = $pearDB->query('SELECT `resource_line` FROM `cfg_resource`');
return $dbResult->fetchAll(\PDO::FETCH_COLUMN);
}
/**
* @param string $commandLine
* @return array{commandPath:string,plugin:string|null,mode:string|null}
*/
function getCommandElements(string $commandLine): array
{
$commandElements = explode(" ", $commandLine);
$matchPluginOption = array_values(preg_grep('/^\-\-plugin\=(\w+)/i', $commandElements) ?? []);
$plugin = $matchPluginOption[0] ?? null;
$matchModeOption = array_values(preg_grep('/^\-\-mode\=(\w+)/i', $commandElements) ?? []);
$mode = $matchModeOption[0] ?? null;
return ['commandPath' => $commandElements[0], 'plugin' => $plugin, 'mode' => $mode];
}
/**
* @param CentreonDB $pearDB
* @param string $commandPath
* @return string
*/
function replaceMacroInCommandPath(CentreonDB $pearDB, string $commandPath): string
{
$explodedCommandPath = explode("/", $commandPath);
$resourceName = $explodedCommandPath[0];
//Match if the first part of the path is a MACRO
if ($resourcePath = getResourcePathByName($pearDB, $resourceName)) {
unset($explodedCommandPath[0]);
return rtrim($resourcePath, "/") . "/" . implode("/", $explodedCommandPath);
}
return $commandPath;
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment