web-dev-qa-db-fra.com

Existe-t-il un moyen de vérifier le type de fichier d'un fichier téléchargé à l'aide de PHP?

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?

17
Grim Reaper

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.

23
gowenfawr

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.

13
user2675345

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']):

  • vérifier les erreurs lors du téléchargement if (!$file['name'] || $file['error']){ return false; }
  • vérifiez que ce fichier a vraiment la taille acceptée par vous if ($file['size'] > MaxPossible || $file['size'] < MinPossible){ return false; }
  • renommer le fichier (si je soumets quelque chose comme ../../../t.py.png, il sera renommé en uniquefilename.png)
  • il est enregistré avec le moins d'autorisations possibles. Sûrement sans aucune autorisation à exécuter. (peut être 640 ou 660)
  • pour être sûr qu'il n'y a aucun moyen d'exécuter XSS, enregistrez-les et servez-les à partir d'un domaine séparé.
4
Salvador Dali

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.

2
Peter

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

  • empêcher l'exécution (utilisez chmod() pour modifier les attributs de fichier et/ou les déplacer vers un sous-domaine statique.),
  • inclusion de fichier (Jamais 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.),
  • injection eval (Ne jamais utiliser de données exif dans un contexte eval, par exemple avec preg_replace().),
  • reniflement de contenu (Forcer le téléchargement avec l'en-tête 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.)
  • xss (Identique à la détection de contenu. Essayez d'éviter l'inclusion de fichiers côté client, si ce n'est pas nécessaire, et utilisez les en-têtes appropriés.)

etc...

J'ai écrit encore plus réponse détaillée sur stackoverflow about PHP uploads, peut-être que ça aide.

2
inf3rno

Il n'y a aucune conception du type de fichier.

Parce que chaque fichier peut être d'une douzaine de formats différents à la fois.

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é.

0
Your Common Sense