Vulnérabilité grave corrigée dans UpdraftPlus 1.22.3
Publié: 2022-02-18Lors d'un audit interne du plugin UpdraftPlus, nous avons découvert une vulnérabilité de téléchargement de sauvegarde arbitraire qui pourrait permettre aux utilisateurs à faibles privilèges comme les abonnés de télécharger les dernières sauvegardes d'un site.
Si elle est exploitée, la vulnérabilité pourrait permettre aux attaquants d'accéder à des informations privilégiées de la base de données du site concerné (par exemple, les noms d'utilisateur et les mots de passe hachés).
Nous avons signalé la vulnérabilité aux auteurs du plugin, et ils ont récemment publié la version 1.22.3 pour y remédier. Les mises à jour automatiques forcées ont également été repoussées en raison de la gravité de ce problème. Si votre site ne l'a pas déjà fait, nous vous recommandons vivement de mettre à jour vers la dernière version (1.22.3) et d'avoir une solution de sécurité établie sur votre site, telle que Jetpack Security.
Vous pouvez trouver le propre avis d'UpdraftPlus ici.
Des détails
Nom du plugin : UpdraftPlus
URI du plugin : https://wordpress.org/plugins/updraftplus/
Auteur : https://updraftplus.com/
La vulnérabilité
Téléchargements de sauvegarde arbitraires
Versions concernées : Toutes les versions entre 1.16.7 et 1.22.3 (version gratuite), et
ID CVE : CVE-2022-0633
ID WPVDB : d257c28f-3c7e-422b-a5c2-e618ed3c0bf3
CVSSv3.1 : 8.5
CWSS : 87,6
Le plugin utilise des "nonces" et des horodatages personnalisés pour identifier en toute sécurité les sauvegardes. Étant donné que la connaissance dudit nonce et de l'horodatage peut permettre à quelqu'un d'accéder à un certain nombre de fonctionnalités du plug-in, il est crucial de s'assurer que ces informations ne sont accessibles qu'à ceux qui en ont légitimement besoin.
Malheureusement, comme nous allons le démontrer, ce n'était pas le cas.
Nonce Fuite
Le premier coupable était situé sur UpdraftPlus_Admin :: process_status_in_heartbeat méthode.
/**
* 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;
}
Il ne s'assurait pas correctement que l'utilisateur envoyant cette demande de pulsation était un administrateur (par exemple via des fonctions comme current_user_can), ce qui était un problème puisque la première chose que cette fonction essaie de faire est de récupérer la liste des tâches de sauvegarde actives via la méthode get_activejobs_list .

Un attaquant pourrait ainsi élaborer une requête malveillante ciblant ce rappel de pulsation pour accéder aux informations sur la dernière sauvegarde du site à ce jour, qui contiendra entre autres le nonce d'une sauvegarde.
Téléchargement de sauvegarde
Il existe plusieurs façons de télécharger des sauvegardes sur UpdraftPlus, dont la plupart sont correctement sécurisées.
/**
* 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
}
}
}
Malheureusement, la méthode UpdraftPlus_Admin::maybe_download_backup_from_email, qui est accrochée à admin_init, n'a pas non plus directement validé les rôles des utilisateurs.
Bien qu'il ait appliqué certaines vérifications indirectement, telles que la vérification de la variable globale $pagenow , des recherches antérieures ont montré que cette variable peut contenir des entrées utilisateur arbitraires. Les mauvais acteurs pourraient utiliser ce point de terminaison pour télécharger des sauvegardes de fichiers et de bases de données en fonction des informations qu'ils ont divulguées à partir du bogue de pulsation mentionné ci-dessus.
Chronologie
2022-02-14 – Premier contact avec UpdraftPlus
2022-02-15 – Nous leur envoyons des détails sur cette vulnérabilité
2022-02-16 - UpdraftPlus 1.22.3 est publié, les mises à jour automatiques forcées sont lancées
Conclusion
Nous vous recommandons de vérifier quelle version du plugin UpdraftPlus votre site utilise, et si elle se trouve dans la plage concernée, mettez-la à jour dès que possible !
Chez Jetpack, nous travaillons dur pour nous assurer que vos sites Web sont protégés contre ces types de vulnérabilités. Nous vous recommandons d'avoir un plan de sécurité pour votre site qui inclut l'analyse et la sauvegarde des fichiers malveillants. Jetpack Security est une excellente option de sécurité WordPress pour garantir la sécurité de votre site et de vos visiteurs.
Crédits
Chercheur original : Marc Montpas
Merci au reste de l'équipe Jetpack Scan pour les commentaires, l'aide et les corrections.