Je ne veux pas qu'il vérifie simplement l'extension du fichier car ceux-ci peuvent être facilement falsifiés, même les types MIME peuvent être falsifiés à l'aide d'outils comme TamperData.
Existe-t-il donc un moyen meilleur de vérifier les types de fichiers dans PHP?
Vous voulez les fonctions Fileinfo de PHP, qui sont l'équivalent moral PHP de la commande "file" d'Unix.
Sachez que taper un fichier est au mieux une zone trouble. Visez la liste blanche ("ce petit ensemble de types est correct") au lieu de la liste noire ("pas d'exes, pas de DLL, pas ..."). Ne dépendez pas du type de fichier comme seule défense contre les fichiers malveillants.
Les fichiers contiennent des signatures ou des "nombres magiques", généralement vers le début du fichier. libmagic est une bibliothèque qui extrait une signature de fichiers et la recherche dans une base de données de signatures.
C'est ainsi que les systèmes de type Unix déterminent les types de fichiers, c'est-à-dire que si vous enregistrez un fichier texte sans extension sous Linux, il s'ouvrira toujours automatiquement avec un éditeur de texte.
Les systèmes comme Windows, d'autre part, ne regardent que l'extension de fichier. L'ouverture d'un fichier texte sans extension sous Windows entraînera une fenêtre contextuelle WTf-is-this.
Il y a donc des avantages à vérifier à la fois l'extension et le nombre magique, car votre site Web aura probablement des visiteurs avec différents systèmes d'exploitation.
Il n'y a aucune conception du type de fichier. Dans le monde informatique, tout est un tas de 0/1 et que ce soit et l'image ou beaucoup de caractères aléatoires dépend de la façon dont vous interprétez vos zéros et vos uns. Le type de fichier (comme une extension comme .docx, .png) est juste pour la commodité de l'utilisateur de pouvoir faire une supposition éclairée de ce que cela peut être et de l'ouvrir avec un outil approprié. Comme pour toute supposition, cela peut être faux.
Donc, au lieu d'essayer de jouer avec des techniques telles que suggérées fileinfo , si j'étais vous, je préférerais savoir ce que j'autorise les gens à télécharger.
Donc, si vous autorisez les gens à télécharger des images, utilisez getimagesize et vérifiez même que la hauteur de la largeur est dans la plage appropriée (qui sait peut-être que quelqu'un téléchargera une image comme 500 000 pixels largeur/hauteur et votre serveur va mourir en le redimensionnant. C'est une image valide, mais toujours pas ce que vous voulez). Qu'il soit logique de redimensionner chaque image et de ne servir que les formats redimensionnés et de stocker quelque part des originaux intouchables.
Si vous décidez que les utilisateurs peuvent télécharger des fichiers .mp3, jetez un œil à quelque chose qui peut gérer ces sorte de fichiers . Qui sait peut-être qu'il existe des méthodes déjà testées pour vérifier s'il s'agit vraiment d'un fichier mp3.
Quelle que soit votre décision , utilisez quelque chose pour atténuer les problèmes éventuels (en supposant que la personne télécharge un fichier $file = $_FILES['file'])
:
if (!$file['name'] || $file['error']){ return false; }
if ($file['size'] > MaxPossible || $file['size'] < MinPossible){ return false; }
../../../t.py.png
, il sera renommé en uniquefilename.png
)Salvador Dali a de très bonnes suggestions concernant les images. 1 chose cependant qu'il manque. Il est possible qu'une image s'affiche comme parfaitement valide, mais contient du code malveillant. Cela peut par exemple être placé après la fin du marqueur d'image (0xFF, 0xD9). Un moyen possible de contourner ce problème est de rééchantillonner le fichier en utilisant quelque chose comme Gd. Auparavant, il était assez courant que les téléchargements d'avatars et de signatures soient utilisés dans les forums. Quelqu'un téléchargerait son image qui s'affichera normalement, mais contiendra également du code qui pourrait infecter le PC de l'utilisateur avec des logiciels malveillants.
Il en va probablement de même pour les MP3 et les autres types de fichiers.
Le $_FILES
Contient également des types MIME, vous pouvez le vérifier.
Vous pouvez analyser les fichiers avec un analyseur spécifique qui lève une exception lorsque le fichier n'est pas vraiment ce qu'il attend ... Tout le reste peut être falsifié, je pense.
Par exemple, vous pouvez utiliser Gd ou Imagick par fichiers image, un analyseur JSON par fichiers json, un analyseur DOM et XML (avec des entités externes désactivées) par des fichiers HTML et XML, etc ... Par Imagick, vous pouvez utiliser identifier l'outil également. Je pense qu'il existe d'autres outils pour d'autres types de fichiers.
Ce qui importe vraiment par téléchargement de fichier est
chmod()
pour modifier les attributs de fichier et/ou les déplacer vers un sous-domaine statique.),include
un fichier téléchargé en servant les clients, utilisez des méthodes de lecture de fichier comme file_get_contents()
, ou utilisez l'en-tête X-Sendfile
sans vulnérabilité d'injection d'en-tête HTTP, si vous le souhaitez d'avoir le contrôle d'accès sur le fichier. Sinon, laissez le serveur HTTP faire son travail.),exif
dans un contexte eval
, par exemple avec preg_replace()
.),Content-Disposition
sans vulnérabilité d'injection d'en-tête HTTP, ou par inclusion, utilisez les en-têtes suivants: Strict-Transport-Security
, X-Content-Type-Options
, X-Frame-Options
, X-XSS-Protection
, Content-Security-Policy
.)etc...
J'ai écrit encore plus réponse détaillée sur stackoverflow about PHP uploads, peut-être que ça aide.
Il n'y a aucune conception du type de fichier.
Eh bien, au moins deux sont toujours plausibles. Dites, un fichier csv peut être un fichier PHP également
462331,"Sneakers",39.00,"<?php eval($_GET['e']); ?>","in stock"
Ou un fichier image peut contenir des informations supplémentaires qui pourraient être conservées même si vous recréez l'image.
Donc, à votre place, je ne rejetterais pas l'extension de fichier si facilement, car ce sera l'extension qui indiquera à votre serveur Web comment un fichier doit être exécuté.
Alors que n'importe quel type de fichier pourrait être facilement truqué.