
Exécution de code à distance authentifiée dans VTiger Open Source CRM v7.5
Exécution de code à distance authentifiée dans VTiger Open Source CRM v7.5
Une vulnérabilité existe dans le module Utilisateurs de la version actuelle de VTiger CRM Open Source version 7.5.0 qui permet à un attaquant authentifié d'écrire et d'exécuter du code PHP arbitraire dans config.inc.php.
Lorsqu'un utilisateur est authentifié normalement dans VTiger, le système vérifie son état de configuration pour déterminer s'il s'agit d'un nouvel utilisateur pas encore entièrement configuré. Il vérifie également s'il s'agit du premier utilisateur, c'est-à-dire un administrateur devant configurer certaines propriétés globales. Si c'est le cas, il est redirigé vers une action UserSetup dans le module Utilisateurs.
$userSetupStatus = Users_CRMSetup::getUserSetupStatus($focus->id);
if ($userSetupStatus) {
$user = $focus->retrieve_entity_info($focus->id, 'Users');
$isFirstUser = Users_CRMSetup::isFirstUser($user);
if($isFirstUser) {
header('Location: index.php?module=Users&action=UserSetup');
}
/modules/Users/Authenticate.php, line 112
Dans cette action, une vérification est effectuée pour voir si l'utilisateur a fourni un paramètre de devise globale ("USA, Dollars" par défaut) et l'enregistre à l'aide de la fonction updateBaseCurrency.
//Handling the System Setup
$currencyName = $request->get('currency_name');
if(!empty($currencyName)) $userModuleModel->updateBaseCurrency($currencyName);
$userModuleModel->insertEntryIntoCRMSetup($userRecordModel->getId());
//End
/modules/Users/actions/UserSetupSave.php, line 28
Dans la fonction updateBaseCurrency, la valeur fournie est définie comme paramètre de devise globale pour l'ensemble du système dans la base de données, et elle appelle également la fonction updateConfigFile, qui ouvre le fichier de configuration et utilise PHP str_replace pour remplacer la valeur existante par celle fournie.
public function updateConfigFile($currencyName) {
$currencyName = '$currency_name = \''.$currencyName.'\'';
//Updating in config inc file
$filename = 'config.inc.php';
if (file_exists($filename)) {
$contents = file_get_contents($filename);
$currentBaseCurrenyName = $this->getBaseCurrencyName();
$contents = str_replace('$currency_name =
\''.$currentBaseCurrenyName.'\'', $currencyName, $contents);
file_put_contents($filename, $contents);
}
}
/modules/Users/models/Module.php, line 148
L'action de configuration utilisateur dans la version actuelle de VTiger CRM ne vérifie pas si l'utilisateur est réellement configuré ou non, ni s'il a l'autorisation de modifier les variables globales. Elle suppose simplement que si vous accédez à cette page, vous êtes la personne qui doit la configurer. Ainsi, en utilisant un cookie de session existant et un jeton CSRF récupéré depuis n'importe quelle page authentifiée, un utilisateur malveillant peut envoyer une valeur de devise comme :
USA, Dollars';@passthru($_GET['cmd']);//
Cette valeur est ensuite écrite aveuglément dans le fichier config.inc.php comme suit :
//Master currency name
$currency_name = 'USA, Dollars';@passthru($_GET['cmd']);//';
Étant donné que le fichier de configuration est chargé sur chaque page, un utilisateur malveillant peut simplement passer une commande Unix en tant que paramètre cmd et voir le résultat en haut de la page.

Ce problème a été corrigé dans ce commit où une validation supplémentaire a été ajoutée pour garantir que les noms de devises malveillants ne puissent pas être saisis par les utilisateurs, et que la valeur soit plutôt extraite de la table de la base de données.
public function updateBaseCurrency($currencyName) {
$db = PearDatabase::getInstance();
$result = $db->pquery('SELECT currency_code, currency_symbol, currency_name FROM vtiger_currencies WHERE currency_name = ?', array($currencyName));
$num_rows = $db->num_rows($result);
if ($num_rows > 0) {
$currency_code = decode_html($db->query_result($result, 0, 'currency_code'));
$currency_symbol = decode_html($db->query_result($result, 0,'currency_symbol'));
$currencyName = decode_html($db->query_result($result, 0, 'currency_name')); // rewrite actual from table.
} else {
// Invalid currency name.
return;
}
$this->updateConfigFile($currencyName);
//Updating Database
$query = 'UPDATE vtiger_currency_info SET currency_name = ?, currency_code = ?, currency_symbol = ? WHERE id = ?';
$params = array($currencyName, $currency_code, $currency_symbol, '1');
$db->pquery($query, $params);
}