• Watch
Published on 26 November 2021

Multiple vulnerabilities found in Concrete CMS making thousands of websites vulnerable

Concrete CMS est conçu pour être facile à utiliser, pour des utilisateurs ayant un minimum de compétences techniques. Il permet aux utilisateurs de modifier le contenu du site directement à partir de la page. Il fournit une gestion de version pour chaque page, similaire au logiciel wiki, un autre type de logiciel de développement de site web. Concrete5 permet aux utilisateurs de modifier les images grâce à un éditeur intégré à la page. En 2021, plus de 62 000 sites Web ont été créés avec Concrete CMS.

De multiples vulnérabilités de sécurité dans le système de gestion de contenu (CMS) open source Concrete CMS pourraient permettre à un attaquant malveillant de prendre le contrôle total du serveur web sous-jacent. Toutes les versions inférieures à 8.5.7 et la version 9.0.0 sont vulnérables.

Découvertes par des chercheurs de Fortbridge, ces vulnérabilités se décomposent de deux race condition et de l'utilisation non sécurisée de la fonction uniqid().

Celles-ci permettent à un attaquant ayant un compte à faible privilège sur le site de réaliser une exécution de code à distance (RCE).

Race condition ? Quézako ?

Selon la bible du pentesteur (OWASP testing guide) : Il s'agit d'une faille qui produit un résultat inattendu lorsque le timing des actions a un impact sur d'autres actions. Un exemple peut être observé sur une application multithread où des actions sont effectuées sur les mêmes données.

Prenons un exemple pour illustrer cette définition barbare :

  • Un compte commun possède 50 euros.
  • Un PEL possède 50 euros.

Alice et Bob souhaitent transférer 5 euros depuis le compte commun vers le PEL. Dans ce cas de figure, nous devrions avoir

  • 40 euros sur le compte commun.
  • 60 euros sur le PEL.

Seulement, des problèmes de concurrence peuvent résulter de ces opérations simultanées :

  • Alice vérifie le solde du compte commun (50 euros)
  • Bob vérifie le solde du compte commun (50 euros)
  • Bob transfère 5 euros du compte commun (qui contiendra ensuite 45 euros) vers le PEL (qui contiendra 55 euros)
  • Alice transfère 5 euros du compte commun (lors de la vérification précédente, le compte possédait 50 euros, donc à l'issue du transfert, il contiendra 45 euros) vers le PEL (55 + 5 = 60 euros) :

Compte commun : 45 euros

PEL : 60 euros

Un article a déjà été écrit à ce sujet sur le blog. Si vous souhaitez une piqure de rappel approfondie : http://bssicert.supertag.fr/la-race-condition-un-ennemi-redoutable-meconnu-des-developpeurs/

Première race condition : téléversement de fichier

En tant qu'utilisateur à faible privilège sur le site, il est possible de téléverser des fichiers depuis un serveur distant. Le CMS va utiliser curl afin de télécharger et écrire localement le fichier. Des vérifications sont faites sur le fichier téléversé afin d'éviter l'utilisation de fichier malveillant comme du code en PHP. Seulement, les chercheurs ont analysé le code et ont découvert que la vérification est faite après avoir téléchargé le fichier en local :

Les fichiers sont téléchargés dans '$temporaryDirectory' - une classe appelée VolatileDirectory

On remarque qu'un répertoire temporaire est créé et que le fichier téléversé est écrit à l'intérieur. Le nom de ce dossier est supposé être aléatoire, seulement $i vallait toujours 0.

Une fois le fichier importé dans le CMS, le dossier entier est supprimé :

Il est donc possible d'accéder au fichier durant ce laps de temps ! La première race condition avait ainsi découverte. Seulement, il est nécessaire de comprendre comment fonctionnait la fonction uniqid() puisque le nom du dossier contenu dans la variable '$temporaryDirectory' l'utilise. C'est ce que nous allons voir.

Fonction uniqid()

Les chercheurs ont remarqué que la fonction exécute simplement gettimeofday() qui renvoie les secondes et les microsecondes. Le paramètre more_entropy n'est pas utilisé dans le code source du CMS, il n'y a donc pas de réelle entropie utilisée ici. La valeur de retour entière est basée sur les secondes/microsecondes Il était donc possible de procéder à une attaque de force brute pour deviner le nom du dossier et d'avoir suffisamment de temps pour le faire, car durant leurs tests initiaux, une requête prenait environ 100ms pour s'exécuter.

Seconde race condition et mise en œuvre

Ainsi, pour deviner le nom du répertoire aléatoire, il est nécessaire de deviner la seconde et la microseconde que le serveur utilisera. Mais une requête prenant environ 100 ms pour s'exécuter, il a été nécessaire de prolonger le temps d'exécution de cette requête autant que possible afin d'avoir le temps de forcer le nom de répertoire

La fonction sleep() a été utilisé. Cela forcera le CMS à conserver le répertoire $temporaryDir pendant 30 à 60 secondes sur le système de fichiers local avant de le supprimer. Assez de temps pour permettre de forcer le nom du répertoire.

Une fois le nom du répertoire trouvé, les chercheurs ont pu demander test.php, le fichier hébergé sur un serveur distant, qui écrit un shell permanent dans le répertoire parent.

En requêtant test.php pendant environ 30 secondes, la deuxième condition de course a été créée, ce qui signifie que test.php sera écrit sur le système de fichiers du CMS et ainsi obtenir une exécution de commande distante sur le serveur.

Code utilisé dans le fichier test.php:

Vous êtes perdus ? Pas de panique, voici un récapitulatif :

  • T0 :  Lancement de la demande de téléchargement ET de la recherche du nom du répertoire volatile. 1 million de possibilités. Les chercheurs ont réussi à envoyer 16-17K requêtes par seconde, soit 500-700K en ~30 secondes, soit une chance sur deux. Première race condition
  • T1 : Nom du répertoire trouvé, mais test.php n'est pas encore écrit dans le répertoire. Début de la recherche de test.php (2ème race condition) qui est toujours écrit après ~30 secondes (à partir de T0).
  • T2 : (~ 30 secondes) test.php est écrit localement, dans le répertoire.
  • T3 : une des requêtes en file d'attente de T1 exécute test.php. Un shell permanent est écrit.
  • T4 : le répertoire et son contenu sont supprimés, mais le shell est déjà écrit.

Voici une vidéo de preuve de concept utilisant Turbo Intruder :

Selon les chercheurs, plus de 62 000 sites Web construits avec le CMS Concrete sont en activité depuis cette année.

Nous vous conseillons donc de mettre à jour votre CMS au plus vite si vous utilisez Concrete CMS et de passer aux versions 8.5.7 et 9.0.1, qui sont déjà disponibles.

Références

https://owasp.org/www-project-web-security-testing-guide/v42/

https://portswigger.net/daily-swig/server-side-vulnerabilities-in-concrete-cms-put-thousands-of-websites-under-threat

https://portswigger.net/research/turbo-intruder-embracing-the-billion-request-attack

https://github.com/PortSwigger/turbo-intruder

https://www.fortbridge.co.uk/research/multiple-vulnerabilities-in-concrete-cms-part1-rce

Article written by
EvaBssi Team