UpdraftPlus 1.22.3'te Ciddi Güvenlik Açığı Düzeltildi

Yayınlanan: 2022-02-18

UpdraftPlus eklentisinin dahili denetimi sırasında, aboneler gibi düşük ayrıcalıklı kullanıcıların bir sitenin en son yedeklerini indirmesine izin verebilecek rastgele bir yedekleme indirme güvenlik açığı ortaya çıkardık.

Bu güvenlik açığından yararlanılırsa, saldırganların etkilenen sitenin veritabanındaki ayrıcalıklı bilgilere (örneğin, kullanıcı adları ve karma parolalar) erişmesine izin verebilir.

Eklentinin yazarlarına güvenlik açığını bildirdik ve kısa süre önce bunu gidermek için 1.22.3 sürümünü yayınladılar. Bu sorunun ciddiyeti nedeniyle zorunlu otomatik güncellemeler de zorlandı. Sitenizde henüz yoksa, en son sürüme (1.22.3) güncelleme yapmanızı ve sitenizde Jetpack Security gibi yerleşik bir güvenlik çözümüne sahip olmanızı şiddetle öneririz.

UpdraftPlus'ın kendi danışmanlığını burada bulabilirsiniz.

Detaylar

Eklenti Adı: UpdraftPlus
Eklenti URI'si: https://wordpress.org/plugins/updraftplus/
Yazar: https://updraftplus.com/

Güvenlik Açığı

Keyfi Yedekleme İndirmeleri

Etkilenen sürümler: 1.16.7 ve 1.22.3 arasındaki her sürüm (Ücretsiz sürüm) ve
CVE-ID: CVE-2022-0633
WPVDB Kimliği: d257c28f-3c7e-422b-a5c2-e618ed3c0bf3
CVSSv3.1: 8.5
CWSS: 87.6

Eklenti, yedekleri güvenli bir şekilde tanımlamak için özel "nonces" ve zaman damgaları kullanır. Söz konusu nonce ve zaman damgasının bilgisinin, birisine eklentinin özelliklerinin birçoğuna erişim sağlayabildiği göz önüne alındığında, bu bilgilerin yalnızca yasal olarak ihtiyaç duyanlar tarafından erişilebilir olduğundan emin olmak çok önemlidir.

Ne yazık ki, göstereceğimiz gibi, durum böyle değildi.

Sızıntı Yok

İlk suçlu UpdraftPlus_Admin::process_status_in_heartbeat üzerinde bulundu yöntem.

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

Bu kalp atışı isteğini gönderen kullanıcının bir yönetici olduğundan emin değildi (örneğin current_user_can gibi işlevler aracılığıyla), bu işlevin yapmaya çalıştığı ilk şey etkin yedekleme görevlerinin listesini get_activejobs_list yöntemiyle almak olduğundan bir sorundu.

Böylece bir saldırgan, sitenin bugüne kadarki en son yedeği hakkındaki bilgilere erişmek için bu kalp atışı geri aramasını hedefleyen kötü niyetli bir istek oluşturabilir ve bu, diğer şeylerin yanı sıra bir yedeğin nonce'sini içerecektir.

Yedek İndirme

UpdraftPlus'ta yedekleri indirmenin birkaç yolu vardır ve bunların çoğu düzgün bir şekilde güvence altına alınmıştır.

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

Ne yazık ki, admin_init'e bağlı UpdraftPlus_Admin::maybe_download_backup_from_email yöntemi de kullanıcıların rollerini doğrudan doğrulamadı.

$pagenow global değişkenini kontrol etmek gibi bazı kontrolleri dolaylı olarak uygulasa da, geçmiş araştırmalar bu değişkenin rastgele kullanıcı girdisi içerebileceğini göstermiştir. Kötü oyuncular, yukarıda belirtilen kalp atışı hatasından sızdırdıkları bilgilere dayanarak dosya ve veritabanı yedeklerini indirmek için bu uç noktayı kullanabilir.

Zaman çizelgesi

2022-02-14 – UpdraftPlus ile ilk temas
2022-02-15 – Onlara bu güvenlik açığıyla ilgili ayrıntıları gönderiyoruz
2022-02-16 – UpdraftPlus 1.22.3 yayınlandı, zorunlu otomatik güncellemeler başlatıldı

Çözüm

Sitenizin UpdraftPlus eklentisinin hangi sürümünü kullandığını kontrol etmenizi ve etkilenen aralıktaysa mümkün olan en kısa sürede güncellemenizi öneririz!

Jetpack olarak, web sitelerinizin bu tür güvenlik açıklarından korunmasını sağlamak için çok çalışıyoruz. Siteniz için kötü amaçlı dosya tarama ve yedeklemeler içeren bir güvenlik planınız olmasını öneririz. Jetpack Security, sitenizin ve ziyaretçilerinizin güvende olmasını sağlamak için harika bir WordPress güvenlik seçeneğidir.

Kredi

Orijinal araştırmacı: Marc Montpas

Geri bildirim, yardım ve düzeltmeler için Jetpack Scan ekibinin geri kalanına teşekkür ederiz.