Contexte :
Les vulnérabilités de téléchargement de fichiers se produisent lorsqu'un serveur Web permet aux utilisateurs de télécharger des fichiers sur son système de fichiers sans valider suffisamment des éléments tels que leur nom, leur type, leur contenu ou leur taille. Le défaut de restreindre correctement ces éléments pourrait signifier qu'une simple fonction de téléchargement d'image peut être utilisée pour télécharger des fichiers arbitraires et potentiellement dangereux à la place. Cela peut même inclure des fichiers de script côté serveur qui permettent l'exécution de code à distance.
Dans certains cas, il suffit de télécharger le fichier lui-même pour causer des dommages. D'autres attaques peuvent impliquer une demande HTTP de suivi pour le fichier, généralement pour déclencher son exécution par le serveur.
L'impact des vulnérabilités de téléchargement de fichiers dépend généralement de deux facteurs clés :
L'aspect du fichier que le site Web ne parvient pas à valider correctement, qu'il s'agisse de sa taille, de son type, de son contenu, etc. Les restrictions imposées sur le fichier une fois qu'il a été téléchargé avec succès. Dans le pire des cas, le type de fichier n'est pas correctement validé et la configuration du serveur permet l'exécution de certains types de fichiers (tels que .php et .jsp) en tant que code. Dans ce cas, un attaquant pourrait potentiellement télécharger un fichier de code côté serveur qui agit comme un shell web, lui accordant un contrôle total sur le serveur.
Si le nom de fichier n'est pas correctement validé, cela pourrait permettre à un attaquant d'écraser des fichiers critiques simplement en téléchargeant un fichier avec le même nom. Si le serveur est également vulnérable à la traversée de répertoire, cela pourrait signifier que les attaquants sont même capables de télécharger des fichiers dans des emplacements inattendus.
Le fait de ne pas s'assurer que la taille du fichier se situe dans les seuils attendus pourrait également permettre une forme d'attaque de déni de service (DoS), où l'attaquant remplit l'espace disque disponible.
Compte tenu des dangers assez évidents, il est rare que les sites Web en direct n'aient aucune restriction sur les fichiers que les utilisateurs sont autorisés à télécharger. Plus couramment, les développeurs mettent en œuvre ce qu'ils pensent être une validation robuste qui est intrinsèquement défectueuse ou peut être facilement contournée.
Par exemple, ils peuvent tenter de mettre sur liste noire les types de fichiers dangereux, mais échouent à prendre en compte les lacunes d'analyse lors de la vérification des extensions de fichier. Comme avec n'importe quelle liste noire, il est également facile d'omettre accidentellement des types de fichiers plus obscurs qui peuvent encore être dangereux.
Dans d'autres cas, le site Web peut tenter de vérifier le type de fichier en vérifiant des propriétés qui peuvent être facilement manipulées par un attaquant. En fin de compte, même des mesures de validation robustes peuvent être appliquées de manière incohérente sur l'hôte et le réseau de répertoire qui composent le site Web, ce qui crée des lacunes qui peuvent être exploitées.
Exploitation des téléchargements de fichiers non restreints pour déployer un shell web
Du point de vue de la sécurité, la situation la plus dangereuse est lorsque le site Web autorise le téléchargement de scripts côté serveur, tels que des fichiers PHP, Java ou Python, et est configuré pour les exécuter en tant que code. Cela crée un moyen facile d'établir un shell web sur le serveur.
Si un attaquant réussit à télécharger un shell web, il peut prendre le contrôle complet du serveur. Cela leur permet d'accéder et de modifier tous les fichiers, de voler des données sensibles et de lancer des attaques sur l'infrastructure interne et d'autres serveurs en dehors du réseau. Par exemple, l'extrait de code PHP ci-dessous peut être utilisé pour lire n'importe quel fichier du système de fichiers du serveur :
<?php echo file_get_contents('/chemin/vers/le/fichier'); ?>
Une fois téléchargé, l'envoi d'une demande pour ce fichier malveillant renverra le contenu du fichier cible dans la réponse. Un shell web plus flexible peut ressembler à ceci :
<?php echo system($_GET['command']); ?>
Avec ce script, un attaquant peut passer une commande système arbitraire via un paramètre de requête comme ceci :
GET /test/exploit.php?command=id HTTP/1.1
Exploitation de la validation de fichier téléchargé défectueuse
Cette section explore les façons dont les serveurs Web tentent de valider et de nettoyer les téléchargements de fichiers, ainsi que la manière dont les attaquants peuvent exploiter les failles de ces mécanismes pour acquérir un shell Web permettant l'exécution de code à distance.
Validation de type de fichier défectueuse
Lorsque les utilisateurs soumettent des formulaires HTML, le navigateur envoie généralement les données dans une requête POST avec le type de contenu application/x-www-form-urlencoded. C'est acceptable pour transmettre du texte de base tel que des noms et des adresses, mais ce n'est pas approprié pour envoyer de grandes quantités de données binaires telles qu'une image ou un fichier PDF. Dans ce cas, multipart/form-data est le type de contenu recommandé.
Imaginez un formulaire qui demande aux utilisateurs de télécharger une image, de fournir une description et de saisir leur nom d'utilisateur. La soumission d'un tel formulaire génère une requête qui ressemble à ceci :
POST /images HTTP/1.1
Host: basic-website.com
Content-Length: 12345
Content-Type: multipart/form-data; boundary=---------------------------012345678901234567890123456
---------------------------012345678901234567890123456
Content-Disposition: form-data; name="image"; filename="test.jpg"
Content-Type: image/jpeg
[...binary content of example.jpg...]
---------------------------012345678901234567890123456
Content-Disposition: form-data; name="description"
This is a description of my image.
---------------------------012345678901234567890123456
Content-Disposition: form-data; name="username"
wiener
---------------------------012345678901234567890123456--
Comme indiqué ci-dessus, le corps du message est divisé en parties distinctes pour chaque entrée de formulaire, avec un en-tête Content-Disposition fournissant des détails de base sur le champ d'entrée correspondant. Ces parties peuvent également avoir leur propre en-tête Content-Type pour informer le serveur du type MIME des données soumises.
Une méthode utilisée par les sites Web pour valider les téléchargements de fichiers consiste à vérifier si l'en-tête Content-Type spécifique à l'entrée correspond au type MIME attendu. Par exemple, si le serveur ne permet que les fichiers d'images, il ne peut permettre que des types tels que image/jpeg et image/png.
Cependant, si la valeur de cet en-tête est implicitement approuvée par le serveur et qu'aucune validation supplémentaire n'est effectuée pour s'assurer que le contenu du fichier correspond au type MIME supposé, cette défense peut être facilement contournée.
Empêcher l'exécution de fichiers dans des répertoires accessibles par l'utilisateur
Empêcher l'exécution de fichiers dans des répertoires accessibles par l'utilisateur est la deuxième ligne de défense après l'interdiction de télécharger des types de fichiers dangereux. Les serveurs n'exécutent généralement que les scripts pour lesquels ils ont été explicitement configurés pour le type MIME donné. Si le script n'est pas autorisé, le serveur peut renvoyer un message d'erreur ou servir le contenu sous forme de texte brut.
GET /static/exploit.php?command=id HTTP/1.1
Host: basic-website.com
HTTP/1.1 200 OK
Content-Type: text/plain
Content-Length: 39
<?php echo system($_GET['command']); ?>
Il est important de noter que la configuration peut différer entre les répertoires, avec un répertoire dans lequel des fichiers fournis par l'utilisateur sont téléchargés ayant des contrôles plus stricts que d'autres emplacements du système de fichiers. Le téléchargement d'un script dans un répertoire différent qui n'est pas destiné à contenir des fichiers fournis par l'utilisateur peut finalement amener le serveur à exécuter le script.
Blacklistage insuffisant des types de fichiers dangereux
Le blacklistage des extensions de fichiers potentiellement dangereuses telles que .php est une manière d'empêcher les utilisateurs de télécharger des scripts malveillants, mais cela est intrinsèquement défectueux car il est difficile de bloquer toutes les extensions de fichiers possibles qui peuvent exécuter du code. Ces listes noires peuvent être contournées en utilisant des extensions de fichiers alternatives moins connues qui peuvent toujours être exécutables, comme .php5, .shtml, etc.
Les développeurs peuvent avoir besoin d'ajouter des directives spécifiques à leurs fichiers de configuration avant que les serveurs tels que Apache n'exécutent les fichiers PHP demandés pour un client. De plus, des fichiers de configuration spéciaux peuvent être créés dans des répertoires individuels pour remplacer ou ajouter aux paramètres globaux, tels que le fichier .htaccess pour les serveurs Apache ou le fichier web.config pour les serveurs IIS.
LoadModule php_module /usr/lib/apache2/modules/libphp.so
AddType application/x-httpd-php .php
Les développeurs peuvent créer des fichiers de configuration spécifiques à un répertoire pour remplacer ou ajouter aux paramètres globaux sur les serveurs, avec les serveurs Apache chargeant la configuration spécifique à un répertoire à partir d'un fichier .htaccess et les serveurs IIS utilisant un fichier web.config. Par exemple, le fichier web.config peut inclure des directives qui autorisent la fourniture de fichiers JSON aux utilisateurs.
<staticContent>
<mimeMap fileExtension=".json" mimeType="application/json" />
</staticContent>
Alors que les serveurs web utilisent ces fichiers de configuration lorsqu'ils sont présents, ils ne sont généralement pas accessibles via des requêtes HTTP. Cependant, certains serveurs peuvent autoriser le téléchargement d'un fichier de configuration malveillant, permettant la cartographie d'extensions de fichiers arbitraires et personnalisées vers des types MIME exécutables, même si l'extension de fichier requise est sur liste noire.
Même les listes noires les plus complètes peuvent potentiellement être contournées en utilisant des techniques d'obscurcissement. Par exemple, si le code de validation est sensible à la casse et ne reconnaît pas qu'exploit.pHp est un fichier .php, la cartographie de l'extension de fichier vers un type MIME qui n'est pas sensible à la casse peut permettre au serveur d'exécuter le fichier PHP malveillant.
D'autres techniques d'obscurcissement incluent la fourniture de plusieurs extensions, l'ajout de caractères de fin, l'utilisation d'un encodage d'URL ou d'un double encodage d'URL, l'ajout de points-virgules ou de caractères nuls codés en URL, et l'utilisation de caractères Unicode multioctets qui peuvent être convertis en octets et en octets nuls après la conversion ou la normalisation Unicode.
Les défenses peuvent consister à supprimer ou remplacer les extensions dangereuses pour empêcher l'exécution de fichiers. Cependant, si cette transformation n'est pas appliquée de manière récursive, un attaquant peut positionner la chaîne interdite pour laisser une extension de fichier valide après sa suppression. Ce ne sont là que quelques exemples des nombreuses techniques d'obscurcissement pouvant être utilisées pour les extensions de fichiers :
exploit.p.phpahp
Validation erronée du contenu des fichiers
Les serveurs plus sécurisés ne font pas confiance implicitement au Content-Type spécifié dans une requête, et essaient plutôt de vérifier que le contenu du fichier correspond à ce qui est attendu. Par exemple, une fonction de téléchargement d'images peut vérifier des propriétés intrinsèques d'une image telles que ses dimensions pour vérifier qu'il s'agit réellement d'un fichier image, et rejeter les téléchargements qui ne répondent pas aux critères attendus.
De même, certains types de fichiers ont des séquences spécifiques d'octets dans leur en-tête ou leur pied de page qui peuvent être utilisées comme empreinte digitale ou signature pour déterminer si le contenu correspond au type attendu. Par exemple, les fichiers JPEG commencent toujours par les octets FF D8 FF.
Bien que ce soit une méthode plus fiable de validation du type de fichier, elle n'est pas totalement infaillible. Avec des outils comme ExifTool, il est possible de créer des fichiers JPEG polyglottes contenant du code malveillant dans leurs métadonnées, rendant difficile la détection et la prévention de tels fichiers lorsqu'ils sont téléchargés
Exploitation des conditions de concurrence pour les téléchargements de fichiers
Les frameworks modernes se sont renforcés contre les attaques de téléchargement de fichiers en mettant en place des précautions telles que le téléchargement vers un répertoire temporaire isolé et la randomisation du nom pour éviter l'écrasement de fichiers existants. Le fichier temporaire est validé avant d'être transféré vers sa destination prévue uniquement s'il est jugé sûr.
Cependant, les développeurs peuvent toujours mettre en place leur propre traitement de téléchargement de fichiers indépendamment de tout framework. Cela peut introduire des conditions de concurrence dangereuses qui peuvent permettre à un attaquant de contourner même la validation la plus robuste.
Par exemple, certains sites Web téléchargent directement le fichier sur le système de fichiers principal et le suppriment s'il échoue à la validation. Ce comportement est typique des sites Web qui comptent sur des logiciels antivirus et d'autres pour détecter les logiciels malveillants. Pendant la courte période où le fichier existe sur le serveur, qui peut être de quelques millisecondes seulement, l'attaquant peut potentiellement l'exécuter.
Ces vulnérabilités sont souvent subtiles, ce qui les rend difficiles à détecter lors de tests en boîte noire, sauf si le code source pertinent est divulgué.
Conditions de concurrence dans les téléchargements de fichiers basés sur une URL
Les conditions de concurrence peuvent également se produire dans les fonctions qui permettent le téléchargement de fichiers en fournissant une URL, car le serveur doit récupérer le fichier depuis Internet et créer une copie locale avant que la validation puisse avoir lieu.
Étant donné que le fichier est chargé via HTTP, les développeurs ne peuvent pas se fier aux mécanismes intégrés du framework pour valider les fichiers en toute sécurité. Ils peuvent créer leurs propres processus pour stocker temporairement et valider le fichier, qui peuvent ne pas être aussi sécurisés.
Par exemple, les développeurs peuvent utiliser un nom aléatoire pour stocker le fichier dans un répertoire temporaire afin d'éviter l'exploitation des conditions de concurrence. Cependant, si le nom de répertoire aléatoire est généré à l'aide de fonctions pseudo-aléatoires telles que uniqid() de PHP, il peut être susceptible de brute-forcing.
Les attaquants peuvent essayer de prolonger le temps de traitement du fichier, ce qui allonge la fenêtre de brute-forcing du nom de répertoire. Une façon d'y parvenir est de créer un fichier plus grand avec la charge utile au début, suivi d'un grand nombre d'octets de remplissage, potentiellement en profitant de la façon dont le fichier est traité en blocs.
Exploitation des vulnérabilités de téléchargement de fichiers sans exécution de code à distance
Les exemples que nous avons explorés jusqu'à présent ont porté sur le téléchargement de scripts côté serveur pour l'exécution de code à distance, qui est la conséquence la plus grave d'une fonction de téléchargement de fichiers non sécurisée. Cependant, les attaquants peuvent exploiter ces vulnérabilités de plusieurs autres manières.
Téléchargement de scripts côté client malveillants
Même si vous ne pouvez pas exécuter de scripts sur le serveur, vous pouvez toujours télécharger des scripts pour des attaques côté client. Par exemple, le téléchargement de fichiers HTML ou d'images SVG peut permettre aux attaquants d'utiliser des balises pour créer des charges utiles de XSS stockées.
Si le fichier téléchargé est affiché sur une page visitée par d'autres utilisateurs, leur navigateur exécutera le script lorsqu'il tentera d'afficher la page. Il est important de noter que en raison des restrictions de la politique de même origine, de telles attaques ne fonctionneront que si le fichier téléchargé est servi à partir de la même origine que celle à partir de laquelle vous l'avez téléchargé.
Exploitation de vulnérabilités dans l'analyse de fichiers téléchargés
Si le fichier téléchargé semble être stocké et servi de manière sécurisée, les attaquants peuvent recourir à l'exploitation de vulnérabilités spécifiques à l'analyse ou au traitement de différents formats de fichier. Par exemple, si le serveur analyse des fichiers XML, tels que les fichiers .doc ou .xls de Microsoft Office, cela pourrait constituer un vecteur potentiel pour les attaques d'injection XXE.
Téléchargement de fichiers en utilisant PUT
Il convient de noter que certains serveurs Web peuvent être configurés pour prendre en charge les demandes PUT, et si les défenses nécessaires ne sont pas en place, les attaquants peuvent utiliser cela comme un moyen alternatif de télécharger des fichiers malveillants, même lorsque la fonction de téléchargement n'est pas disponible via l'interface Web.
PUT /images/exploit.php HTTP/1.1
Host: website.com
Content-Type: application/x-httpd-php
Content-Length: 54
<?php echo file_get_contents('/path/to/file'); ?>
Comment prévenir les vulnérabilités de téléchargement de fichiers
Permettre aux utilisateurs de télécharger des fichiers est une fonctionnalité courante et ne devrait pas être dangereux si les précautions nécessaires sont prises. La mise en œuvre des pratiques suivantes peut être un moyen efficace de protéger vos sites Web contre ces vulnérabilités :
Vérifiez l'extension de fichier par rapport à une liste blanche d'extensions autorisées plutôt qu'une liste noire d'extensions interdites. Il est plus facile d'identifier les extensions que vous souhaitez autoriser que de deviner celles qu'un attaquant pourrait essayer de télécharger. Assurez-vous que le nom de fichier ne contient pas de sous-chaînes qui pourraient être interprétées comme une séquence de répertoires ou de traversée (comme "../"). Renommez les fichiers téléchargés pour éviter les collisions qui pourraient entraîner l'écrasement de fichiers existants. Ne téléchargez pas les fichiers dans le système de fichiers permanent du serveur tant qu'ils n'ont pas été entièrement validés. Dans la mesure du possible, utilisez un framework bien établi pour prétraiter les téléchargements de fichiers au lieu de tenter de développer vos propres mécanismes de validation.