Vulnerabilitatea gravă a fost remediată în UpdraftPlus 1.22.3

Publicat: 2022-02-18

În timpul unui audit intern al pluginului UpdraftPlus, am descoperit o vulnerabilitate arbitrară de descărcare de rezervă care ar putea permite utilizatorilor cu privilegii reduse, cum ar fi abonații, să descarce cele mai recente copii de siguranță ale unui site.

Dacă este exploatată, vulnerabilitatea ar putea acorda atacatorilor acces la informații privilegiate din baza de date a site-ului afectat (de exemplu, nume de utilizator și parole codificate).

Am raportat vulnerabilitatea autorilor pluginului și au lansat recent versiunea 1.22.3 pentru a o soluționa. Actualizările automate forțate au fost, de asemenea, impuse din cauza gravității acestei probleme. Dacă site-ul dvs. nu a făcut-o deja, vă recomandăm insistent să actualizați la cea mai recentă versiune (1.22.3) și să aveți o soluție de securitate stabilită pe site-ul dvs., cum ar fi Jetpack Security.

Puteți găsi propriul consilier al UpdraftPlus aici.

Detalii

Nume plugin: UpdraftPlus
URI plugin: https://wordpress.org/plugins/updraftplus/
Autor: https://updraftplus.com/

Vulnerabilitatea

Descărcări arbitrare de rezervă

Versiuni afectate: fiecare versiune între 1.16.7 și 1.22.3 (versiunea gratuită) și
CVE-ID: CVE-2022-0633
ID WPVDB: d257c28f-3c7e-422b-a5c2-e618ed3c0bf3
CVSSv3.1: 8.5
CWSS: 87,6

Pluginul folosește „nonce” și marcaje temporale personalizate pentru a identifica în siguranță copiile de rezervă. Având în vedere că cunoștințele menționate nonce și marca temporală pot oferi cuiva acces la câteva dintre funcțiile pluginului, este crucial să vă asigurați că aceste informații sunt accesibile numai celor care au nevoie de ele în mod legitim.

Din păcate, așa cum vom demonstra, nu a fost cazul.

Nonce Leak

Primul vinovat a fost localizat pe UpdraftPlus_Admin::process_status_in_heartbeat metodă.

	/**
	 * 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;
	}

Nu s-a asigurat în mod corespunzător că utilizatorul care trimite această solicitare de bătăi de inimă este un administrator (de exemplu, prin funcții precum current_user_can), ceea ce a fost o problemă, deoarece primul lucru pe care îl încearcă această funcție este să apuce lista de joburi de backup active prin metoda get_activejobs_list .

Un atacator ar putea astfel să creeze o solicitare rău intenționată care vizează acest apel invers pentru a obține acces la informații despre cea mai recentă copie de rezervă a site-ului de până acum, care va conține, printre altele, nonceul unui backup.

Descărcare de rezervă

Există câteva modalități de a descărca copii de rezervă pe UpdraftPlus, dintre care majoritatea au fost securizate corespunzător.

	/**
	 * 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
		}
	}
}

Din păcate, metoda UpdraftPlus_Admin::maybe_download_backup_from_email, care este conectată la admin_init, nici nu a validat direct rolurile utilizatorilor.

Deși a aplicat unele verificări indirect, cum ar fi verificarea variabilei globale $pagenow , cercetările anterioare au arătat că această variabilă poate conține intrări arbitrare ale utilizatorului. Actorii răi ar putea folosi acest punct final pentru a descărca copii de siguranță ale fișierelor și bazei de date pe baza informațiilor pe care le-au scurs din eroarea ritmului cardiac menționat mai sus.

Cronologie

2022-02-14 – Contact inițial cu UpdraftPlus
2022-02-15 – Le trimitem detalii despre această vulnerabilitate
2022-02-16 - UpdraftPlus 1.22.3 este lansat, actualizările automate forțate lansate

Concluzie

Vă recomandăm să verificați ce versiune a pluginului UpdraftPlus folosește site-ul dvs. și, dacă se află în intervalul afectat, actualizați-l cât mai curând posibil!

La Jetpack, muncim din greu pentru a ne asigura că site-urile dvs. sunt protejate de aceste tipuri de vulnerabilități. Vă recomandăm să aveți un plan de securitate pentru site-ul dvs. care să includă scanarea fișierelor rău intenționate și backup-uri. Jetpack Security este o opțiune excelentă de securitate WordPress pentru a vă asigura că site-ul și vizitatorii sunt în siguranță.

credite

Cercetator original: Marc Montpas

Mulțumim restului echipei Jetpack Scan pentru feedback, ajutor și corecții.