ช่องโหว่ที่รุนแรงได้รับการแก้ไขแล้วใน UpdraftPlus 1.22.3

เผยแพร่แล้ว: 2022-02-18

ในระหว่างการตรวจสอบภายในของปลั๊กอิน UpdraftPlus เราพบช่องโหว่ในการดาวน์โหลดข้อมูลสำรองโดยอำเภอใจ ซึ่งอาจอนุญาตให้ผู้ใช้ที่มีสิทธิพิเศษต่ำ เช่น สมาชิกสามารถดาวน์โหลดข้อมูลสำรองล่าสุดของไซต์ได้

หากถูกโจมตี ช่องโหว่ดังกล่าวอาจทำให้ผู้โจมตีสามารถเข้าถึงข้อมูลที่ได้รับสิทธิพิเศษจากฐานข้อมูลของเว็บไซต์ที่ได้รับผลกระทบ (เช่น ชื่อผู้ใช้และรหัสผ่านที่แฮช)

เรารายงานช่องโหว่ดังกล่าวไปยังผู้เขียนปลั๊กอิน และเพิ่งเปิดตัวเวอร์ชัน 1.22.3 เพื่อแก้ไข บังคับให้อัปเดตอัตโนมัติถูกผลักออกไปเนื่องจากความรุนแรงของปัญหานี้ หากไซต์ของคุณยังไม่มี เราขอแนะนำให้คุณอัปเดตเป็นเวอร์ชันล่าสุด (1.22.3) และมีโซลูชันการรักษาความปลอดภัยที่เป็นที่ยอมรับในไซต์ของคุณ เช่น Jetpack Security

คุณสามารถหาคำแนะนำของ UpdraftPlus ได้ที่นี่

รายละเอียด

ชื่อปลั๊กอิน: UpdraftPlus
URI ของปลั๊กอิน: https://wordpress.org/plugins/updraftplus/
ผู้แต่ง: https://updraftplus.com/

จุดอ่อน

ดาวน์โหลดการสำรองข้อมูลโดยพลการ

เวอร์ชันที่ได้ รับผลกระทบ: ทุกเวอร์ชันระหว่าง 1.16.7 ถึง 1.22.3 (เวอร์ชันฟรี) และ
CVE-ID: CVE-2022-0633
รหัส WPVDB: d257c28f-3c7e-422b-a5c2-e618ed3c0bf3
CVSSv3.1: 8.5
CWSS: 87.6

ปลั๊กอินใช้ "nonce" และการประทับเวลาที่กำหนดเองเพื่อระบุข้อมูลสำรองอย่างปลอดภัย เนื่องจากความรู้เกี่ยวกับ nonce และการประทับเวลาดังกล่าวสามารถให้ผู้อื่นเข้าถึงคุณลักษณะบางอย่างของปลั๊กอินได้ การทำให้แน่ใจว่าข้อมูลนี้สามารถเข้าถึงได้เฉพาะผู้ที่ต้องการเท่านั้นจึงเป็นสิ่งสำคัญ

น่าเสียดาย ตามที่เราจะแสดงให้เห็น มันไม่ใช่อย่างนั้น

น็อนซ์ รั่ว

ผู้ร้ายคนแรกตั้งอยู่ที่ 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

ผู้โจมตีสามารถสร้างคำขอที่เป็นอันตรายซึ่งกำหนดเป้าหมายการโทรกลับแบบฮาร์ทบีตเพื่อเข้าถึงข้อมูลเกี่ยวกับการสำรองข้อมูลล่าสุดของไซต์จนถึงปัจจุบัน ซึ่งเหนือสิ่งอื่นใดจะมี nonce ของข้อมูลสำรอง

ดาวน์โหลดสำรอง

มีสองสามวิธีในการดาวน์โหลดข้อมูลสำรองบน ​​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
		}
	}
}

น่าเสียดายที่เมธอด UpdraftPlus_Admin::maybe_download_backup_from_email ซึ่งเชื่อมต่อกับ admin_init ไม่ได้ตรวจสอบบทบาทของผู้ใช้โดยตรงเช่นกัน

แม้ว่าจะใช้การตรวจสอบทางอ้อม เช่น การตรวจสอบตัวแปรส่วนกลาง $pagenow การวิจัยในอดีตแสดงให้เห็นว่าตัวแปรนี้สามารถมีอินพุตของผู้ใช้ตามอำเภอใจได้ ผู้ไม่หวังดีสามารถใช้ปลายทางนี้เพื่อดาวน์โหลดไฟล์และสำรองฐานข้อมูลตามข้อมูลที่รั่วไหลจากจุดบกพร่องของ heartbeat ดังกล่าว

เส้นเวลา

2022-02-14 – การติดต่อครั้งแรกกับ UpdraftPlus
2022-02-15 – เราส่งรายละเอียดเกี่ยวกับช่องโหว่นี้ไปให้พวกเขา
2022-02-16 – เปิดตัว UpdraftPlus 1.22.3 บังคับให้อัปเดตอัตโนมัติเปิดตัว

บทสรุป

เราขอแนะนำให้คุณตรวจสอบเวอร์ชันของปลั๊กอิน UpdraftPlus ที่ไซต์ของคุณใช้ และหากอยู่ภายในช่วงที่ได้รับผลกระทบ ให้อัปเดตโดยเร็วที่สุด!

ที่ Jetpack เราทำงานอย่างหนักเพื่อให้แน่ใจว่าเว็บไซต์ของคุณได้รับการปกป้องจากช่องโหว่ประเภทนี้ เราขอแนะนำให้คุณมีแผนความปลอดภัยสำหรับไซต์ของคุณที่มีการสแกนไฟล์ที่เป็นอันตรายและการสำรองข้อมูล Jetpack Security เป็นหนึ่งในตัวเลือกการรักษาความปลอดภัย WordPress ที่ยอดเยี่ยมเพื่อให้แน่ใจว่าไซต์และผู้เยี่ยมชมของคุณปลอดภัย

เครดิต

นักวิจัยต้นฉบับ: Marc Montpas

ขอขอบคุณทีมงาน Jetpack Scan ที่เหลือสำหรับความคิดเห็น ความช่วยเหลือ และการแก้ไข