В плагине Patreon для WordPress обнаружены уязвимости

Опубликовано: 2021-03-26

Во время внутреннего аудита плагина Patreon для WordPress команда Jetpack Scan обнаружила несколько слабых мест, которые позволили бы кому-то завладеть веб-сайтом.

Об этих уязвимостях сообщили авторам плагина, которые оперативно выпустили версию 1.7.2, исправляющую все эти проблемы. Если вы используете более старую версию плагина, обновите ее сегодня!

Читайте все технические подробности. Если это выходит за рамки вашей головы, не волнуйтесь. Мы предлагаем Jetpack Scan для сканирования вредоносных программ и автоматического обновления или удаления.

Наша команда выявила различные векторы атак, в том числе уязвимости, связанные с раскрытием локальных файлов, подделкой межсайтовых запросов (CSRF) и отражением межсайтовых сценариев (XSS).

Уязвимости Local File Disclosure — это ошибки, которые злоумышленники могут использовать для получения доступа к важной информации, такой как секретные ключи веб-сайта и учетные данные базы данных. Уязвимости отраженного межсайтового скриптинга и подделки межсайтовых запросов — это проблемы, которые позволяют злоумышленникам выполнять определенные действия от имени ничего не подозревающих пользователей, заставляя их переходить по тщательно созданным вредоносным ссылкам.

В случае эксплуатации некоторые из них могут позволить злоумышленникам захватить уязвимые веб-сайты.

Уязвимость раскрытия локальных файлов
Затронутые версии: < 1.7.0
Идентификатор CVE: CVE-2021-24227
CVSSv3: 7,5
КВСС: 83,6

	public static function servePatronOnlyImage( $image=false ) {

		if ( ( !isset( $image ) OR !$image ) AND isset( $_REQUEST['patron_only_image'] ) ) {
			$image = $_REQUEST['patron_only_image'];
		}
		
		if ( !$image OR $image == '') {
			// This is not a rewritten image request. Exit.
			return;
		}

		if ( !( isset( $_REQUEST['patreon_action'] ) AND $_REQUEST['patreon_action'] == 'serve_patron_only_image' ) ) {
			return;	
		}

		$upload_locations = wp_upload_dir();

		// We want the base upload location so we can account for any changes to date based subfolders in case there are

		$upload_dir = substr( wp_make_link_relative( $upload_locations['baseurl'] ) , 1 );	

		$image = get_site_url() . '/' . $upload_dir . '/' . $image;
		
		if ( current_user_can( 'manage_options' ) ) {
			Patreon_Protect::readAndServeImage( $image );	
		}			
		
		// Below define can be defined in any plugin to bypass core locking function and use a custom one from plugin
		// It is independent of the plugin load order since it checks if it is defined.
		// It can be defined by any plugin until right before the_content filter is run.

		if ( apply_filters( 'ptrn/bypass_image_filtering', defined( 'PATREON_BYPASS_IMAGE_FILTERING' ) ) ) {
			Patreon_Protect::readAndServeImage( $image );
		}
	
		// Check if the image is protected:

		$attachment_id = attachment_url_to_postid( $image );
	
		// attachment_url_to_postid returns 0 if it cant find the attachment post id
		
		if ( $attachment_id == 0 ) {
			
			// Couldnt determine attachment post id. Try to get id from thumbnail
			$attachment_id = Patreon_Protect::getAttachmentIDfromThumbnailURL( $image );
	
			//No go. Have to get out and serve the image normally
			if ( $attachment_id == 0 OR !$attachment_id ) {
				Patreon_Protect::readAndServeImage( $image );

Patreon-Connect содержал локальную уязвимость раскрытия файлов, которой мог злоупотребить любой посетитель сайта. Используя этот вектор атаки, злоумышленник может украсть важные внутренние файлы, такие как wp-config.php, который содержит учетные данные базы данных и криптографические ключи, используемые при создании одноразовых номеров и файлов cookie.

В случае успешного использования этот недостаток безопасности может привести к полному захвату сайта злоумышленниками.

Отраженный XSS в форме входа
Затронутые версии: < 1.7.2
Идентификатор CVE: CVE-2021-24228
CVSSv3: 8,8
КВСС: 80,6

	public static function processPatreonMessages() {
		
		$patreon_error = '';
		if ( isset( $_REQUEST['patreon_error'] ) ) {
			
			// If any specific error message is sent from Patreon, prepare it
			$patreon_error = ' - Patreon returned: ' . $_REQUEST['patreon_error'];
			
		}

		if ( isset( $_REQUEST['patreon_message'] ) ) {
			
			return '<p class="patreon_message">' . apply_filters( 'ptrn/error_message', self::$messages_map[ $_REQUEST['patreon_message'] ] . $patreon_error ) . '</p>';

Patreon-Connect перехватывает форму входа в WordPress (wp-login.php) и предлагает разрешить пользователям проходить аутентификацию на сайте, используя свою учетную запись Patreon. К сожалению, некоторая логика регистрации ошибок за кулисами позволяла отображать пользовательский ввод на странице входа в несанированном виде.

Чтобы успешно использовать эту уязвимость, злоумышленнику необходимо обманом заставить свою жертву посетить заминированную ссылку, содержащую вредоносный код Javascript. Поскольку Javascript запускается в контексте браузера жертвы, злоумышленник может настроить код, скрытый в этой ссылке, чтобы делать все, что ему позволяют привилегии этого пользователя.

Если эта атака окажется успешной против администратора, скрипт может полностью захватить сайт.

Отражено XSS в действии AJAX 'patreon_save_attachment_patreon_level'
Затронутые версии: < 1.7.2
Идентификатор CVE: CVE-2021-24229
CVSSv3: 8,8
КВСС: 80,6

		$args = array (
			'attachment_id' => $attachment_id,
			'patreon_level' => $_REQUEST['patreon_attachment_patreon_level'],
			'message' => $message,
		);
		
		echo self::make_image_lock_interface( $args	);
	public function make_image_lock_interface( $args = array() ) {
		
		$interface = '';
		
		$interface .=  '<div class="patreon_image_lock_modal_content">';
		$interface .=  '<span class="patreon_image_lock_modal_close">&times;</span>';

		$interface .=  ' <form id="patreon_attachment_patreon_level_form" action="/wp-admin/admin-ajax.php" method="post">';
		$interface .=  '<h1 class="patreon_image_locking_interface_heading">Lock Image</h1>';
		$interface .=  '<div class="patreon_image_locking_interface_level">';
		$interface .=  '<span class="patreon_image_locking_interface_input_prefix">$<input id="patreon_attachment_patreon_level" type="text" name="patreon_attachment_patreon_level" value="' . $args['patreon_level'] . '" / ></span>';

Плагин также использует хук AJAX для обновления уровня залога, необходимого подписчикам Patreon для доступа к данному вложению. Это действие доступно для учетных записей пользователей с привилегией «manage_options» (т. е. только для администраторов).

К сожалению, один из параметров, используемых в этой конечной точке AJAX, не очищается перед печатью обратно пользователю, поэтому риск, который он представляет, такой же, как и в предыдущей уязвимости XSS, которую мы описали.

CSRF позволяет злоумышленникам перезаписывать/создавать пользовательские метаданные
Затронутые версии: < 1.7.0
Идентификатор CVE: CVE-2021-24230
CVSSv3: 6,5
КВСС: 42

	public function toggle_option() {
		
		if( !( is_admin() && current_user_can( 'manage_options' ) ) ) {
			return;
		}
		
		$current_user = wp_get_current_user();
		
		$option_to_toggle = $_REQUEST['toggle_id'];
		
		$current_value = get_user_meta( $current_user->ID, $option_to_toggle, true );
		
		$new_value = 'off';
		
		if( !$current_value OR $current_value == 'off' ) {
			$new_value = 'on';			
		}
		
		update_user_meta( $current_user->ID, $option_to_toggle, $new_value );
		
	}

Некоторые конечные точки не проверяли, что полученный запрос был отправлен после законного действия пользователя, что можно сделать с помощью одноразовых номеров. Одна из этих незащищенных конечных точек позволяла злоумышленникам создать заминированную ссылку, которая перезаписывала или создавала произвольные пользовательские метаданные в учетной записи жертвы после посещения.

В случае эксплуатации эта ошибка может быть использована для перезаписи метаданных «wp_capabilities», которые содержат роли и привилегии затронутой учетной записи пользователя. Это по существу заблокирует их доступ к сайту, заблокировав им доступ к платному контенту.

CSRF позволяет злоумышленникам отключать сайты от Patreon
Затронутые версии: < 1.7.0
Идентификатор CVE : CVE-2021-24231
CVSSv3: 6,5
КЧСС: 26.1

			if ( isset( $_REQUEST['patreon_wordpress_action'] ) AND $_REQUEST['patreon_wordpress_action'] == 'disconnect_site_from_patreon' AND is_admin() AND current_user_can( 'manage_options' ) ) {

			// Admin side, user is admin level. Perform action:
			
			// To disconnect the site from a particular creator account, we will delete all options related to creator account, but we will leave other plugin settings and post gating values untouched
			
			$options_to_delete = array(
				'patreon-custom-page-name',
				'patreon-fetch-creator-id',
				'patreon-creator-tiers',
				'patreon-creator-last-name',
				'patreon-creator-first-name',
				'patreon-creator-full-name',
				'patreon-creator-url',
				'patreon-campaign-id',
				'patreon-creators-refresh-token-expiration',
				'patreon-creator-id',
				'patreon-setup-wizard-last-call-result',
				'patreon-creators-refresh-token',
				'patreon-creators-access-token',
				'patreon-client-secret',
				'patreon-client-id',
				'patreon-setup_is_being_done',
				'patreon-setup-done',
				'patreon-currency-sign',
			);
			
			// Ask the API to delete this client:
			
			$creator_access_token = get_option( 'patreon-creators-access-token', false );
			$client_id 			  = get_option( 'patreon-client-id', false );
				
			// Exceptions until v1 v2 transition is complete
			
			$api_version = get_option( 'patreon-installation-api-version' );

			if ( $api_version == '1' ) {

				// Delete override - proceed with deleting local options
				
				foreach ( $options_to_delete as $key => $value ) {
					delete_option( $options_to_delete[$key] );
				}
				
				update_option( 'patreon-installation-api-version', '2' );
				update_option( 'patreon-can-use-api-v2', true );
				
				wp_redirect( admin_url( 'admin.php?page=patreon_wordpress_setup_wizard&setup_stage=reconnect_0') );
				exit;
			}
			

Эта уязвимость похожа на предыдущую тем, что это тот же тип атаки (CSRF), но она нацелена на администраторов. Этот конкретный вектор атаки работает так же, как и предыдущий. Злоумышленнику необходимо заставить вошедшего в систему администратора перейти по специально созданной ссылке.

Поскольку эта конкретная конечная точка может отключить сайт от Patreon, злоумышленники, нацеленные на этот вектор атаки, также могут сделать именно это, что предотвратит синхронизацию нового контента с сайтом.

График

  • Первоначальная попытка контакта (неудачная) — 4 декабря.
  • Вторая попытка контакта — 11 декабря.
  • Авторы признают отчет – 15 декабря
  • Выпущена версия 1.7.0 — 5 января
  • Мы сообщаем о двух дополнительных проблемах XSS — 9 марта
  • Авторы признают второй доклад – 9 марта
  • Вышла версия 1.7.2 — 11 марта

Вывод

Мы рекомендуем вам проверить текущую версию плагина Patreon-Connect, который вы используете на своем сайте, и, если это не 1.7.2, обновить ее как можно скорее!

В Jetpack мы прилагаем все усилия, чтобы ваши веб-сайты были защищены от уязвимостей такого типа. Чтобы быть на шаг впереди любых новых угроз, попробуйте Jetpack Scan, который включает сканирование безопасности и автоматическое удаление вредоносных программ.

Кредиты

Это раскрытие информации о безопасности стало возможным благодаря Джорджу Стефанису, Фиораванте Соуза, Мигелю Нето, Бенедикту Сингеру и Марку Монпасу.