UpdraftPlus1.22.3で修正された重大な脆弱性

公開: 2022-02-18

UpdraftPlusプラグインの内部監査中に、サブスクライバーなどの特権の低いユーザーがサイトの最新のバックアップをダウンロードできる可能性のある、任意のバックアップダウンロードの脆弱性を発見しました。

この脆弱性が悪用されると、攻撃者は影響を受けるサイトのデータベースからの特権情報(ユーザー名やハッシュ化されたパスワードなど)にアクセスできるようになる可能性があります。

プラグインの作成者に脆弱性を報告し、最近、それに対処するためにバージョン1.22.3をリリースしました。 この問題の重大度のため、強制自動更新もプッシュされています。 サイトがまだ更新されていない場合は、最新バージョン(1.22.3)に更新し、JetpackSecurityなどの確立されたセキュリティソリューションをサイトに用意することを強くお勧めします。

UpdraftPlus独自のアドバイザリはここにあります。

詳細

プラグイン名:UpdraftPlus
プラグインURI:https://wordpress.org/plugins/updraftplus/
著者:https://updraftplus.com/

脆弱性

任意のバックアップのダウンロード

影響を受けるバージョン: 1.16.7〜1.22.3(無料バージョン)のすべてのバージョン、および
CVE-ID: CVE-2022-0633
WPVDB ID: d257c28f-3c7e-422b-a5c2-e618ed3c0bf3
CVSSv3.1: 8.5
CWSS: 87.6

プラグインは、カスタムの「ナンス」とタイムスタンプを使用して、バックアップを安全に識別します。 上記のナンスとタイムスタンプの知識を考えると、プラグインの機能のかなりの数に誰かがアクセスできるようになるため、この情報に合法的に必要な人だけがアクセスできるようにすることが重要です。

残念ながら、これから説明するように、そうではありませんでした。

ノンスリーク

最初の犯人はUpdraftPlus_Admin::process_status_in_heartbeatにありました 方法。

	/**
	 * Receive Heartbeat data and respond.
	 *
	 * Processes data received via a Heartbeat request, and returns additional data to pass back to the front end.
	 *
	 * @param array $response - Heartbeat response data to pass back to front end.
	 * @param array $data     - Data received from the front end (unslashed).
	 */
	public function process_status_in_heartbeat($response, $data) {
		if (!is_array($response) || empty($data['updraftplus'])) return $response;
		try {
			$response['updraftplus'] = $this->get_activejobs_list(UpdraftPlus_Manipulation_Functions::wp_unslash($data['updraftplus']));
		} catch (Exception $e) {
			$log_message = 'PHP Fatal Exception error ('.get_class($e).') has occurred during get active job list. Error Message: '.$e->getMessage().' (Code: '.$e->getCode().', line '.$e->getLine().' in '.$e->getFile().')';
			error_log($log_message);
			$response['updraftplus'] = array(
				'fatal_error' => true,
				'fatal_error_message' => $log_message
			);
		// @codingStandardsIgnoreLine
		} catch (Error $e) {
			$log_message = 'PHP Fatal error ('.get_class($e).') has occurred during get active job list. Error Message: '.$e->getMessage().' (Code: '.$e->getCode().', line '.$e->getLine().' in '.$e->getFile().')';
			error_log($log_message);
			$response['updraftplus'] = array(
				'fatal_error' => true,
				'fatal_error_message' => $log_message
			);
		}

		if (UpdraftPlus_Options::user_can_manage() && isset($data['updraftplus']['updraft_credentialtest_nonce'])) {
			if (!wp_verify_nonce($data['updraftplus']['updraft_credentialtest_nonce'], 'updraftplus-credentialtest-nonce')) {
				$response['updraftplus']['updraft_credentialtest_nonce'] = wp_create_nonce('updraftplus-credentialtest-nonce');
			}
		}

		$response['updraftplus']['time_now'] = get_date_from_gmt(gmdate('Y-m-d H:i:s'), 'D, F j, Y H:i');

		return $response;
	}

このハートビート要求を送信するユーザーが管理者であることを適切に保証しませんでした(たとえば、current_user_canなどの関数を介して)。これは、この関数が最初に実行しようとするのはget_activejobs_listメソッドを介してアクティブなバックアップジョブのリストを取得するためです。

したがって、攻撃者は、このハートビートコールバックを標的とする悪意のある要求を作成して、これまでのサイトの最新のバックアップに関する情報にアクセスする可能性があります。

バックアップダウンロード

UpdraftPlusにバックアップをダウンロードする方法はいくつかあり、そのほとんどは適切に保護されています。

	/**
	 * Find out if the current request is a backup download request, and proceed with the download if it is
	 */
	public function maybe_download_backup_from_email() {
		global $pagenow;
		if ((!defined('DOING_AJAX') || !DOING_AJAX) && UpdraftPlus_Options::admin_page() === $pagenow && isset($_REQUEST['page']) && 'updraftplus' === $_REQUEST['page'] && isset($_REQUEST['action']) && 'updraft_download_backup' === $_REQUEST['action']) {
			$findexes = empty($_REQUEST['findex']) ? array(0) : $_REQUEST['findex'];
			$timestamp = empty($_REQUEST['timestamp']) ? '' : $_REQUEST['timestamp'];
			$nonce = empty($_REQUEST['nonce']) ? '' : $_REQUEST['nonce'];
			$type = empty($_REQUEST['type']) ? '' : $_REQUEST['type'];
			if (empty($timestamp) || empty($nonce) || empty($type)) wp_die(__('The download link is broken, you may have clicked the link from untrusted source', 'updraftplus'), '', array('back_link' => true));
			$backup_history = UpdraftPlus_Backup_History::get_history();
			if (!isset($backup_history[$timestamp]['nonce']) || $backup_history[$timestamp]['nonce'] !== $nonce) wp_die(__("The download link is broken or the backup file is no longer available", 'updraftplus'), '', array('back_link' => true));
			$this->do_updraft_download_backup($findexes, $type, $timestamp, 2, false, '');
			exit; // we don't need anything else but an exit
		}
	}
}

残念ながら、admin_initにフックされているUpdraftPlus_Admin :: maybe_download_backup_from_emailメソッドも、ユーザーのロールを直接検証しませんでした。

$ pagenowグローバル変数のチェックなど、間接的にいくつかのチェックを適用しましたが、過去の調査では、この変数に任意のユーザー入力を含めることができることが示されています。 悪意のある攻撃者は、このエンドポイントを使用して、前述のハートビートのバグから漏洩した情報に基づいてファイルとデータベースのバックアップをダウンロードする可能性があります。

タイムライン

2022-02-14 –UpdraftPlusとの最初の接触
2022-02-15 –この脆弱性に関する詳細を送信します
2022-02-16 – UpdraftPlus 1.22.3がリリースされ、強制自動更新が開始されました

結論

サイトで使用しているUpdraftPlusプラグインのバージョンを確認し、影響を受ける範囲内にある場合は、できるだけ早く更新することをお勧めします。

Jetpackでは、お客様のWebサイトがこれらのタイプの脆弱性から保護されるように努めています。 悪意のあるファイルのスキャンとバックアップを含むサイトのセキュリティ計画を立てることをお勧めします。 Jetpack Securityは、サイトと訪問者の安全を確保するための優れたWordPressセキュリティオプションの1つです。

クレジット

元の研究者:マーク・モンパス

フィードバック、ヘルプ、および修正を提供してくれたJetpackScanチームの残りのメンバーに感謝します。