
VTiger Open Source CRM v7.5における認証済みリモートコード実行
VTiger Open Source CRM v7.5 における認証済みリモートコード実行
VTiger CRM Open Source バージョン 7.5.0 の現在のリリースの Users モジュールには、認証された攻撃者が config.inc.php に任意の PHP コードを書き込んで実行できるようにする脆弱性が存在します。
ユーザーが通常どおり VTiger に認証されると、VTiger はセットアップ状況を確認し、まだ完全に設定されていない新規ユーザーかどうかを判断します。また、特定のグローバルプロパティを設定すべき管理者である最初のユーザーかどうかも確認します。該当する場合、ユーザーは Users モジュールの UserSetup アクションにリダイレクトされます。
$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
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']);//';
設定ファイルはすべてのページで読み込まれるため、悪意のあるユーザーは cmd パラメータとして Unix コマンドを渡すだけで、ページの先頭に出力を表示させることができます。

この問題はこのコミットで修正されました。ユーザーが悪意のある通貨名を入力できないようにする追加の検証が実装され、代わりに値がデータベーステーブルから取得されるようになりました。
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);
}