25 mars 2019

WordPress 5.1 : Explications de la vulnérabilité permettant la prise de contrôle d’un serveur à distance (CVE-2019-9787)

1. Introduction

D’après une étude réalisée par W3Techs (Web Technology Surveys), WordPress représenterait plus de 33% (pourcentage datant du mois de mars 2019) de l’ensemble des sites Web disponible sur Internet. Ce système de gestion de contenu (CMS) est de ce fait exposé et la cible de nombreux pirates informatiques.

Il y a quelques jours, une vulnérabilité critique a été identifiée par Simon Scannell. Ce consultant en sécurité de la société RIPS Technologies a découvert une vulnérabilité de type CSRF (Cross-Site Request Forgery) au sein de la version 5.1 de WordPress. Le scénario mis en avant permet à un attaquant non authentifié, une fois la vulnérabilité CSRF exploitée, de réaliser de l’exécution de code à distance menant à la compromission totale du serveur Web.

La faille de sécurité CSRF est présente dans le champ commentaire de WordPress. Ces derniers, activés par défaut, rendent quasiment l’ensemble des versions présentes sur Internet vulnérable. Toutes les versions de WordPress antérieures à la version 5.1.1 de WordPress sont ainsi vulnérables.

2. Scénario d’exploitation

Avant toute chose, nous allons brièvement définir ce qu’est une vulnérabilité de type Cross-Site Request Forgery. L’idée principale de cette faille de sécurité réside dans le fait de transmettre (par un quelconque moyen – mail, forum, etc.) une requête spécialement forgée qui pointe sur une fonctionnalité de l’application Web (changement de mots de passe, élévation de privilèges, etc.), afin que la victime l’exécute à son insu et avec ses propres privilèges. De la sorte, la victime devient complice de l’attaque sans même s’en rendre compte (voire trop tard). L’action étant initiée par la victime (authentifiée sur l’application), un grand nombre de systèmes d’authentification sont contournés de la sorte.

Ainsi, un attaquant distant est en mesure de prendre le contrôle de n’importe quel site WordPress dont la fonctionnalité de commentaires n’est pas désactivée, en incitant un administrateur à visiter (via des techniques de Social Engineering) un site Web malveillant contrôlé par l’attaquant. Une fois que l’administrateur visite ce site malveillant, le code d’exploitation de la CSRF entraîne une cascade de failles logiques menant à l’exécution de code arbitraire sur le serveur de la victime.

Le scénario d’exploitation de la vulnérabilité peut se résumer à ces 6 étapes :

3. Analyse de la vulnérabilité

3.1 Remise dans le contexte

Tout d’abord, pour comprendre l’analyse de la vulnérabilité, il est important de préciser que WordPress offre la possibilité de lier des articles distants entre eux via des rétroliens. Il existe deux types de rétroliens :

  • le Trackback
  • le Pingback

Ainsi, lorsqu’un rédacteur de blog lie l’un de ses articles à l’un des vôtres, une notification de type Trackback ou Pingback vous sera envoyée. Il est du ressort de l’administrateur de modérer l’approbation ou la suppression de la notification à l’image de la gestion des commentaires réalisée sur un article. La validation d’un rétrolien a pour conséquence d’afficher un commentaire sur l’article comportant le lien vers l’article distant.

Il existe quelques différences entre ces deux rétroliens. En effet, les Pingbacks incluent uniquement un lien vers l’article et sont envoyés automatiquement. Les Trackbacks se veulent un peu plus verbeux, car affichent le titre de l’article tiers, un extrait ainsi que le lien vers le site distant. Une autre différence importante est que ces derniers doivent être envoyés manuellement par l’auteur de l’article.

La fonctionnalité d’ajout de commentaires de WordPress n’implémente pas de mécanisme de vérification CSRF. Ce choix est volontaire et connu depuis 2009 d’après le chercheur en sécurité Simon Scannell. En effet, l’implémentation de cette vérification entraînerait la rupture du fonctionnement des rétroliens Pingbacks et Trackbacks.

L’absence de cette validation de commentaires pourrait permettre à un attaquant de créer des commentaires de la part d’un administrateur via une attaque CSRF. De plus, les administrateurs sont habilités à utiliser des balises HTML dangereuses telles que <script> par exemple, ce qui constitue un problème de sécurité. Ainsi, en combinant les deux vulnérabilités un attaquant serait en mesure de rédiger un commentaire à la place d’un administrateur contenant du code HTML/JavaScript malveillant (injection de type Cross-Site Scripting – XSS persistante).

Pour ces raisons précises, les développeurs de WordPress génèrent un nonce (valeur unique aléatoire) supplémentaire pour les administrateurs au sein du formulaire de commentaires. Si un administrateur soumet un commentaire avec un nonce valide, alors le commentaire sera créé tel quel, c.-à-d. sans aucun assainissement (pas de suppression des balises sensibles permettant l’exécution de code JavaScript par exemple). Dans le cas où le nonce ne serait pas valide, le commentaire est publié, mais sera filtré par une fonction d’assainissement.

Pour illustrer ces propos, voici un aperçu du code source de la page PHP /wp-includes/comment.php gérant les commentaires de la version vulnérable 5.1 de WordPress :

Au sein de cette section de code (lignes 3240 à 3248), deux fonctions sont appelées :

  • kses_remove_filters()
  • kses_init_filters()

La fonction vulnérable est celle qui initialise les filtres (kses_init_filters()) :

L’assainissement général des commentaires se réalise via la directive wp_filter_kses. Néanmoins, si l’utilisateur qui crée le commentaire est un administrateur (retour de la fonction current_user_can(‘unfiltered_html’) est évalué à VRAI) et qu’aucun nonce valide n’est fourni, alors la directive appelée est wp_filter_post_kses.

Les deux directives sont similaires et permettent globalement de retirer les attributs ou balises HTML « dangereux » au sein du commentaire à publier. La première directive est très restrictive et autorise uniquement les balises et attributs HTML élémentaires telles que les balises de lien (<a> avec l’attribut href par exemple). La seconde, bien que plus permissive, supprime tout de même les balises et attributs HTML pouvant mener à des vulnérabilités de type injections XSS.

3.2 Contournement des mesures de sécurité

Néanmoins, le chercheur a découvert un moyen de contourner le dernier filtre dans un cas bien particulier. En effet, certains attributs qui ne sont pas attendus à être présents dans les commentaires sont manipulés et filtrés de manière erronée, conduisant à une injection d’attributs arbitraires. À l’issue de l’assainissement du commentaire, les balises de type lien hypertexte <a> sont modifiées dans l’esprit d’optimisation de référencement.

Note : L’attribut rel d’une balise <a> par exemple ne peut être défini que si le commentaire est filtré via la directive wp_filter_post_kses().

Le traitement de cet attribut se réalise dans le fichier /wp-includes/formatting.php via la fonction wp_rel_nofollow_callback() :

Cette fonction analyse la chaîne d’attributs de la balise <a> présente au sein du commentaire et l’enregistre au sein d’un dictionnaire (tableau associatif) nommé atts (ligne 3004). Les clefs de ce dictionnaire correspondent aux noms des attributs, et leurs valeurs correspondent au contenu des valeurs des attributs associés.

La vulnérabilité se manifeste par l’absence d’assainissement des lignes de code 3022 à 3024. En effet, la boucle itère sur les clefs du dictionnaire atts et concatène l’ensemble des valeurs associées au sein de la variable html. Celle-ci est par la suite directement injectée (en supprimant au préalable les espaces de début et de fin – appel à la fonction trim) dans la nouvelle balise <a> qui est retournée par la fonction vulnérable.

Si un attaquant utilise, par exemple, la charge malveillante suivante :

<a title='XSS" onmouseover=codeMalveillant() id="1' rel='nofollow'>

alors la fonction d’assainissement sera exécutée, mais la chaîne de caractères injectée sera mal filtrée (à cause de l’utilisation de guillemets simples).

Lors de la reconstruction de la balise <a> par la fonction, la charge malveillante analysée deviendra :

<a title="XSS" onmouseover=codeMalveillant() id="1" rel="nofollow">

En effet, la valeur de l’attribut title est entourée de guillemets doubles (ligne 3023) et la valeur de l’attribut id est également terminée par un guillemet double.

Le commentaire est ensuite enregistré au sein de la base de données de WordPress avec la charge malveillante de l’attaquant. De ce fait, l’attaquant a été en mesure de mener une injection XSS persistante (car enregistrée en base) via l’exploitation de la CSRF.

La balise <a> vue précédemment permet de générer un lien hypertexte, néanmoins pour parfaire l’attaque et pour la rendre automatique, il est possible d’utiliser une balise <iframe>. Cette attaque est possible si jamais le serveur Apache, sous-jacent le CMS WordPress, ne dispose pas de l’entête « X-Frame-Options ». Par défaut, cet entête n’est pas présent.

En associant la balise <iframe> à l’attribut onmouseover l’attaquant fait en sorte que dès que la souris de l’administrateur bouge, la charge malveillante injectée (XSS) est instantanément déclenchée. Cette action se réalise en arrière-plan sans que l’administrateur ne s’en aperçoive.

Par défaut, WordPress permet aux administrateurs d’éditer directement des fichiers PHP (thèmes ou plugins) via le tableau de bord d’administration. Ainsi, en insérant une porte dérobée PHP au sein d’un thème ou d’un plugin, l’attaquant est en mesure d’obtenir un accès au système sous-jacent et par conséquent d’exécuter des commandes systèmes arbitraires. Cette dernière étape mène à la compromission totale du site Web de la victime.

4. Conclusion

La vulnérabilité publique référencée CVE-2019-9787 a été identifiée le 24 octobre 2018 par Simon Scannell.

En réponse, WordPress a fourni un correctif de cette vulnérabilité le 13 mars 2019. Il est vivement conseillé de mettre à jour WordPress vers la version 5.1.1 disponible sur le site de l’éditeur. Si les mises à jour automatiques n’ont pas été désactivées, alors les administrateurs de WordPress n’ont pas d’actions particulières à fournir.

Dans le cas où il n’est pas possible de mettre à jour vers la dernière version pour des raisons de compatibilité avec des thèmes ou plugins spécifiques, alors il est également possible de se protéger de cette vulnérabilité en désactivant la fonctionnalité de commentaires. La déconnexion de la session d’administrateur après chaque utilisation peut également rendre cette attaque plus difficile.

Enfin, bien que la configuration du serveur Web sous-jacent soit indépendante de la configuration du WordPress, le durcissement de la configuration de celui-ci permettrait de ralentir / complexifier l’exploitation de la vulnérabilité.

Cyril LORENZETTO
Consultant BSSI

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *