14 mai 2019

Typo3 PharStreamWrapper : Vulnérabilité présente au sein des principaux CMS (Drupal, Joomla, Typo3) pouvant mener à la prise de contrôle à distance du serveur

1. Introduction

De nombreux systèmes de gestion de contenu (CMS) se basent sur le langage de programmation PHP. Ce langage de programmation désigné pour du développement Web a été créé il y a 25 ans (1994) par Rasmus Lerdorf. PHP est très répandu dans le monde des sites Web et une grande communauté le fait vivre à travers les temps. Pour faciliter le développement, de nombreux paquets (composants) sont disponibles librement. Un paquet particulier a récemment fait parler de lui, car il présentait une vulnérabilité importante référencée CVE-2019-11831. Ce paquet, développé par la société Typo3, se prénomme PharStreamWrapper (alias phar-stream-wrapper).

Avant de se pencher sur ce que fait ce composant PHP, commençons par définir ce qu’est une archive Phar. Une archive Phar est une archive PHP (Php archive), c’est-à-dire c’est un fichier comportant plusieurs scripts PHP. Elle permet de mettre à disposition une application PHP complète dans un unique fichier et de l’exécuter à partir de ce fichier sans pour autant l’extraire sur le disque. Une analogie peut être faite avec les archives Jar (Java archive) pour les fichiers Java.

À titre comparatif, lorsque nous souhaitons utiliser et donc inclure des fonctions PHP présentes dans un fichier tiers (ici script2.php), nous faisons appel à la fonction PHP include au sein de notre script1.php :

# cat script1.php
<?php
    include '/chemin/vers/script2.php';
?>

Ce que réalise l’interpréteur PHP est une transformation du chemin en un flux de type « file ». Ceci devient donc ‘file:///chemin/vers/script2.php’ et permet d’accéder aux fichiers locaux du serveur.

De la même manière, il est possible d’accéder au contenu d’un fichier tiers présent dans une archive Phar via la syntaxe suivante :

# cat script3.php
<?php
    include 'phar:///chemin/vers/archive.phar/script4.php';
?>

Pour ce faire, il est alors nécessaire d’utiliser le type de flux Phar.

À quoi sert alors le composant PharStreamWrapper ? Ce composant PHP permet de vérifier si l’archive Phar est valide et comporte l’extension éponyme. À ce sujet, l’année dernière, en juillet 2018, une vulnérabilité sur ce même composant avait déjà été remontée. En effet, il était possible de définir n’importe quelle extension pour une archive Phar, ouvrant la porte à des effets de bords et attaques plus sophistiquées (ex : uploader une archive Phar avec une extension .png).

2. Analyse de la vulnérabilité

La vulnérabilité référencée CVE-2019-11831 a été identifiée par Daniel Le Gall, chercheur en sécurité chez SCRT SA (Suisse). Si celui-ci se base sur la méthode de calcul de Drupal, la vulnérabilité serait considérée comme critique. Néanmoins le chercheur tient à préciser que cette nouvelle vulnérabilité n’est pas aussi critique que les précédentes (notamment les Drupalgeddon 1 et 2), car nécessite certains prérequis.

Ici, le composant PharStreamWrapper ne vérifie pas le paramètre fourni et permet de réaliser une attaque de type Directory Traversal ou encore dite Path Traversal. Plus généralement, ce type de vulnérabilité permet à un attaquant d’accéder à des ressources présentes au sein d’un répertoire différent du chemin présenté (en général en dehors de la racine du serveur Web). Pour ce faire, il est nécessaire d’utiliser les caractères universels ‘..’ qui permettent de remonter l’arborescence d’un système de fichiers (le caractère ‘.’ signifiant le répertoire courant).

À titre d’exemple, voici l’arborescence d’un serveur fictif :

Si nous supposons que le paramètre f permet de lire un fichier (ex : user.txt) et qu’il n’est pas filtré, alors le site serait vulnérable à ce type d’attaque et permettrait à un attaquant présent sur la page index.php de l’application d’accéder au fichier texte secret.txt (présent dans le répertoire admin). La charge malveillante serait de la forme : http://monsitedemo.fr/application/index.php?f=../admin/secret.txt au lieu du lien initial prédéfini http://monsitedemo.fr/application/index.php?f=user.txt

Dans le cas présent, des mécanismes de sécurité ont été mis en place, notamment lors de l’appel aux fonctions file_exists() ou stat() d’une archive Phar. En effet, le nom de base (base name) doit être déterminé avant de traiter le flux phar://

Par exemple, dans le cadre du code source PHP ci-dessous, le nom de base est /path/bad.phar alors que /phar-content.txt est le fichier auquel le script PHP demande l’accès.

<?php
    $userSubmittedPath = 'phar:///path/bad.phar/phar-content.txt';
    file_exists($userSubmittedPath);
?>

Cependant, le chemin suivant ‘phar:///path/bad.phar/../good.phar’ est interprété de manière erronée est devient : ‘/path/good.phar’.

<?php
    // Helper::determineBaseFile(
    //    'phar:///path/bad.phar/../good.phar'
    // )
    // is incorrectly resolved to
    // base name '/path/good.phar'
    // ... which is used in order to allow invocation
    if ($interceptor->assert('/path/good.phar')) {
        $wrapper->invokeInternalStreamWrapper(
          'stat',
          'phar:///path/bad.phar/../good.phar'
        );
    }
?>

Ainsi, un attaquant est en mesure de contourner le mécanisme de protection mis en place contre les désérialisations non sécurisées. C’est-à-dire qu’il peut envoyer des données non fiables (objets PHP spécialement forgés par l’attaquant) pour abuser de la logique de l’application. Par conséquent, l’archive Phar malveillante (bad.phar) ne sera pas vérifiée par le code de l’application. Seul good.phar sera en réalité vérifiée et permettra de passer outre les mesures de sécurité implémentées, pour finalement exécuter l’archive contrôlée par l’attaquant.

Il est important de noter que le contexte varie suivant l’utilisation du composant vulnérable. Dans le cas présent, le chercheur en sécurité s’est basé sur le CMS Drupal et a montré, qu’avec un utilisateur disposant des droits d’administration des thèmes (ex : les graphistes), qu’il est possible d’exécuter du code arbitraire sur le serveur sous-jacent l’application PHP.

3. Conclusion

La vulnérabilité publique référencée CVE-2019-11831 a été signalée le 22 février 2019 par Daniel à Drupal.

Depuis quelques jours, les correctifs ont été fournis par les éditeurs.

Ainsi, il est recommandé de mettre à jour PharStreamWrapper vers les versions 3.1.1 (pour PHP v7.0 et versions ultérieures) et 2.1.1 (pour PHP v5.3 et versions ultérieures) dans le cas de l’utilisation du CMS Typo3 (éditeurs n’ont pas fourni d’indice de criticité).

Pour le CMS Joomla, la vulnérabilité est considérée faible et affecte les versions 3.9.3 à 3.9.5. Le correctif est présent dans la version 3.9.6.

Enfin, pour le CMS Drupal, le correctif de la branche 8.7 est la version 8.7.1. Celui de la branche 8.6 est la version 8.6.16. Pour les applications s’exécutant avec Drupal 7, il sera nécessaire d’installer la version 7.67.

Laisser un commentaire

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