Le 13 juillet 2020, notre équipe Threat Intelligence a été alertée d’une vulnérabilité récemment corrigée dans Newsletter, un plugin WordPress avec plus de 300000 installations. En enquêtant sur cette vulnérabilité, nous avons découvert deux vulnérabilités supplémentaires plus graves, notamment une vulnérabilité XSS (Cross-Site Scripting) et une vulnérabilité d’injection d’objets PHP.

Nous avons contacté l’auteur du plugin le 15 juillet 2020 et avons reçu une réponse le lendemain. Après avoir complètement divulgué la vulnérabilité le 16 juillet 2020, l’auteur du plugin a publié un correctif le lendemain, le 17 juillet 2020.

Une règle de pare-feu pour se protéger contre la vulnérabilité Reflected Cross-Site Scripting a été publiée pour les clients Wordfence Premium le 15 juillet 2020 et sera disponible pour les utilisateurs gratuits de Wordfence 30 jours plus tard, le 14 août 2020.

Bien que la vulnérabilité PHP Object Injection nécessiterait l’installation d’un logiciel vulnérable supplémentaire et que notre protection intégrée PHP Object Injection se soit protégée contre les exploits les plus courants, nous avons déterminé qu’un contournement était possible. Par précaution, nous avons créé une règle de pare-feu supplémentaire et l’avons publiée aux utilisateurs de Wordfence Premium le 28 juillet 2020. La règle de pare-feu PHP Object Injection sera disponible pour les utilisateurs gratuits de Wordfence à la même date que la règle XSS pour ce plugin , le 14 août 2020.


Le plugin Newsletter comprend un éditeur visuel complet qui peut être utilisé pour créer des newsletters et des campagnes par e-mail visuellement attrayantes. Il utilise une fonction AJAX, tnpc_render_callback, pour afficher les blocs modifiés en fonction d’un ensemble d’options envoyées dans la requête AJAX. Malheureusement, les versions vulnérables n’ont pas filtré ces options, mais les ont passées sur une deuxième fonction, restore_options_from_request qui utilisait plusieurs méthodes pour décoder les options transmises avant de les afficher en utilisant le render_block fonction.

    function tnpc_render_callback() {
        $block_id = $_POST['b'];
        $wrapper = isset($_POST['full']);
        $options = $this->restore_options_from_request();

        $this->render_block($block_id, $wrapper, $options);
        wp_die()

En tant que tel, il était possible pour un attaquant de faire afficher du JavaScript malveillant de plusieurs manières. La méthode la plus simple impliquerait d’envoyer un POST demande à wp-admin/admin-ajax.php avec le action paramètre défini sur tnpc_render, les b paramètre défini sur html, et le options paramètre défini sur JavaScript arbitraire. Alternativement, une demande similaire avec le options paramètre défini sur un tableau vide options[]= et le encoded_options un paramètre défini sur une chaîne JSON encodée en base64 contenant du JavaScript arbitraire entraînerait également le rendu de JavaScript dans le navigateur d’un utilisateur connecté.

            if (isset($_POST['encoded_options'])) {
                $decoded_options = $this->options_decode($_POST['encoded_options']);
    function options_decode($options) {

        // Start compatibility
        if (is_string($options) && strpos($options, 'options[') !== false) {
            $opts = array();
            parse_str($options, $opts);
            $options = $opts['options'];
        }
        // End compatibility

        if (is_array($options)) {
            return $options;
        }

        $tmp = json_decode($options, true);
        if (is_null($tmp)) {
            return json_decode(base64_decode($options), true);
        } else {
            return $tmp;
        }
    }

Nous avons discuté des vulnérabilités Reflected XSS dans un post précédent. Bien qu’ils exigent qu’un attaquant incite une victime à effectuer une action spécifique (comme cliquer sur un lien spécialement conçu), ils peuvent toujours être utilisés pour injecter des portes dérobées ou ajouter des utilisateurs administratifs malveillants. Si un attaquant trompait une victime en lui envoyant une requête contenant un JavaScript malveillant à l’aide de l’une de ces méthodes, le JavaScript malveillant serait décodé et exécuté dans le navigateur de la victime.


Bien que l’éditeur de newsletter n’ait pas permis aux utilisateurs de niveau inférieur d’enregistrer les modifications apportées à une newsletter donnée, le même tnpc_render_callback La fonction AJAX était toujours accessible à tous les utilisateurs connectés, y compris les abonnés. Cela a introduit une vulnérabilité d’injection d’objets PHP via le restore_options_from_request fonction. Cette fonction données non sérialisées transmises via le options[inline_edits] paramètre. En tant que tel, un attaquant connecté en tant qu’abonné pourrait envoyer un POST demande à wp-admin/admin-ajax.php avec le action paramètre défini sur tpnc_render et le options[inline_edits] paramètre défini sur un objet PHP sérialisé.

        if (isset($_POST['options']) && is_array($_POST['options'])) {
            // Get all block options
            $options = stripslashes_deep($_POST['options']);

            // Deserialize inline edits when
            // render is preformed on saving block options
            if (isset($options['inline_edits']) && is_serialized($options['inline_edits'])) {
                $options['inline_edits'] = unserialize($options['inline_edits']);
            }

Bien que le plugin Newsletter lui-même n’utilise aucun code permettant une exploitation supplémentaire, cette vulnérabilité pourrait être utilisée pour injecter un objet PHP qui pourrait être traité par le code d’un autre plugin ou thème et utilisé pour exécuter du code arbitraire, télécharger des fichiers ou n’importe quel nombre d’autres tactiques qui pourraient conduire à la prise de contrôle du site.

Comment fonctionne l’injection d’objets PHP?

PHP peut utiliser une méthode appelée «sérialisation» pour stocker des données complexes. Dans la plupart des cas, les données sérialisées se composent de tableaux key => value, par exemple:
a:2:{s:11:"productName";s:5:"apple";s:7:"price";i:10;}
Cet exemple de données sérialisées comprend un productName propriété définie sur apple et un price propriété définie sur 10.

Les données sérialisées sont utiles pour stocker les paramètres en masse, et de nombreux paramètres WordPress sont stockés sous forme de données sérialisées. Malheureusement, les données sérialisées peuvent également causer un problème de sécurité car elles peuvent être utilisées pour stocker des objets PHP.

Que sont les objets PHP?

La plupart du code PHP moderne est orienté objet, ce qui signifie que le code est organisé en «classes». Ces classes agissent comme un modèle de base contenant à la fois des variables (appelées «propriétés») et des fonctions (appelées «méthodes»). Un programme en cours d’exécution peut alors créer des «objets» basés sur ces modèles ou classes. Cela crée non seulement une structure claire et concise pour la gestion des données, ce qui facilite la maintenance du code, mais permet au même code d’être réutilisé pour plusieurs tâches similaires.

Par exemple, une boutique en ligne pourrait utiliser une seule classe pour les produits avec des propriétés (variables) comprenant $price et $productNameet créez un objet différent pour chaque produit. Chaque objet utiliserait la même fonction (méthode) pour calculer la taxe, mais pourrait utiliser un prix et un nom de produit différents.

Si un plugin désérialise les données fournies par les utilisateurs sans nettoyer l’entrée de cet utilisateur, alors un attaquant peut envoyer une charge utile spécialement conçue qui serait désérialisée dans un objet PHP.

À lui seul, un objet PHP injecté n’est pas particulièrement dangereux. Cela change, cependant, si la classe sur laquelle elle est basée utilise des «méthodes magiques».

Quelles sont les méthodes magiques?

Les méthodes magiques sont des fonctions spéciales qui peuvent être ajoutées à une classe qui décrivent ce qu’elle doit faire lorsque certains événements se produisent.

Par exemple, le __destruct La fonction est utilisée dans de nombreuses classes pour «nettoyer» une fois qu’un objet est utilisé, et dans de nombreux cas, elle le fait en supprimant des fichiers.

Voici un exemple très basique de classe vulnérable qui calcule les prix des produits, stocke un journal et supprime le journal une fois terminé:

class Product{

    public $price;
    public $productName;
    public $savedPriceFile;

    function __construct($price, $productName){
        $this->price=$price;
        $this->productName=$productName;
        $this->savedPriceFile=$productName."pricefile.log";
    }

    function calculateTotal($quantity) {
        $total=$this->price * $quantity;
        echo ($total);
        file_put_contents($this->savedPriceFile, $total);
    }

    function __destruct(){
        unlink($this->savedPriceFile);
    }

}

Si ce code s’exécutait sur un site qui présentait également une vulnérabilité PHP Object Injection, un attaquant pourrait supprimer le wp-config.php contenant les paramètres de configuration de base du site WordPress en envoyant une charge utile similaire à ce qui suit:

O:7:"Product":3:{s:5:"price";i:2;s:11:"productName";s:6:"apples";s:14:"savedPriceFile";s:13:"wp-config.php";}

Cela injecterait un Product objet, avec le $productName mis à apples, les $price mis à 2, et un $savedPriceFile propriété définie sur wp-config.php. Même si l’objet ne peut être utilisé par rien d’autre, le __destruct fonction s’exécuterait, supprimant tout $savedPriceFile a été réglé sur. Dans ce cas, la suppression du wp-config.php fichier réinitialiserait le site et permettrait à un attaquant de prendre le relais en pointant la nouvelle configuration du site vers une base de données distante sous son contrôle.

Exploiter avec succès cette chaîne d’événements, également connue sous le nom de «chaîne POP», nécessite un certain degré d’effort, car elle nécessite:

  • Code qui désérialise l’entrée utilisateur (une vulnérabilité d’injection d’objets).
  • Code qui utilise une méthode magique de manière non sécurisée.
  • Ces deux éléments doivent être chargés en même temps.

En raison du fait que de nombreux plugins et thèmes chargent une partie ou la totalité de leurs classes à chaque requête sur le site, ce n’est pas une restriction aussi importante que cela puisse paraître. De plus, bien que l’utilisation non sécurisée de ces «méthodes magiques» soit moins courante qu’elle ne l’était dans le passé, une telle utilisation n’est pas considérée comme une vulnérabilité en soi car elle nécessite la présence d’une vulnérabilité PHP Object Injection pour être exploitée.

Enfin, même si un attaquant peut avoir besoin de savoir quels plugins sont installés afin d’adapter son attaque à une chaîne POP donnée, il est souvent assez simple de le déterminer avec des outils d’analyse. La bonne nouvelle est que ces vulnérabilités sont difficiles à exploiter automatiquement en masse, sauf dans les cas où une vulnérabilité d’injection d’objets PHP et une méthode magique non sécurisée sont toutes deux utilisées dans le même plugin.

Chronologie

13 juillet 2020 – Notre équipe Threat Intelligence commence à enquêter sur une vulnérabilité récemment corrigée dans le plugin Newsletter.
14 juillet 2020 – Au cours de notre enquête, nous découvrons 2 vulnérabilités non corrigées.
15 juillet 2020 – Nous publions une règle de pare-feu pour la vulnérabilité XSS reflétée aux utilisateurs de Wordfence Premium et contactons l’auteur du plugin.
16 juillet 2020 – Nous recevons une réponse de l’auteur du plugin et fournissons une divulgation complète.
17 juillet 2020 – L’auteur du plugin publie un correctif pour les deux vulnérabilités.
28 juillet 2020 – Nous déterminons qu’une règle de pare-feu supplémentaire est nécessaire pour assurer une couverture complète de la vulnérabilité PHP Object Injection et la publier pour les utilisateurs de Wordfence Premium.
14 août 2020 – Les deux règles de pare-feu deviennent disponibles pour les utilisateurs gratuits de Wordfence.

Conclusion

Dans cet article de blog, nous avons discuté de 2 vulnérabilités dans le plugin Newsletter, y compris une vulnérabilité XSS reflétée et une vulnérabilité d’injection d’objets PHP. Nous avons également expliqué ce que sont les vulnérabilités d’injection d’objets PHP et comment elles peuvent être exploitées.

Nous vous recommandons vivement de mettre à jour la dernière version du plugin Newsletter dès que possible. Au moment d’écrire ces lignes, c’est la version 6.8.3.

Wordfence Premium les utilisateurs sont protégés contre la majorité des attaques potentielles depuis le 15 juillet 2020 et sont entièrement protégés depuis le 28 juillet 2020. Les sites exécutant toujours la version gratuite de Wordfence recevront des règles de pare-feu protégeant contre les deux vulnérabilités le 14 août 2020.

Un merci spécial à Stefano Lissa et à l’équipe de la newsletter pour leur réponse rapide à la correction de ces vulnérabilités.


Source link