49 votes

Comment vérifier les types de fichiers téléchargés en PHP ?

Sur le site web de PHP, la seule vérification réelle qu'ils suggèrent est d'utiliser is_uploaded_file() ou move_uploaded_file() , ici . Bien sûr, vous ne souhaitez généralement pas que les utilisateurs téléchargent n'importe quel type de fichier, pour diverses raisons.

Pour cette raison, j'ai souvent utilisé une vérification "stricte" des types de mime. Bien sûr, cette méthode est très imparfaite, car les types de fichiers sont souvent erronés et les utilisateurs ne peuvent pas télécharger leur fichier. Il est également très facile de les falsifier et/ou de les modifier. En outre, chaque navigateur et système d'exploitation les traite différemment.

Une autre méthode consiste à vérifier l'extension, qui est bien sûr encore plus facile à modifier que le type mime.

Si vous ne voulez que des images, utilisez quelque chose comme getimagesize() fonctionnera.

Qu'en est-il des autres types de fichiers ? Des PDF, des documents Word ou des fichiers Excel ? Ou même des fichiers texte uniquement ?

Edit : Si vous n'avez pas mime_content_type ou Fileinfo et system("file -bi $uploadedfile") vous donne le mauvais type de fichier, quelles sont les autres options ?

0 votes

El getimagesize() indique clairement que vous ne devez pas utiliser cette fonction pour valider si une image est une image. Do not use getimagesize() to check that a given file is a valid image. Use a purpose-built solution such as the Fileinfo extension instead. php.net/manual/fr/function.getimagesize.php

33voto

davr Points 9556

Jetez un coup d'œil à mime_content_type ou Fileinfo . Ce sont des commandes PHP intégrées qui permettent de déterminer le type d'un fichier en regardant le contenu du fichier. Consultez également les commentaires sur les deux pages ci-dessus, il y a d'autres bonnes suggestions.

Personnellement, j'ai eu de la chance en utilisant quelque chose qui est essentiellement system("file -bi $uploadedfile") mais je ne suis pas sûr que ce soit la meilleure méthode.

21 votes

System("file -bi -- ".escapeshellarg($uploadedfile)) est plus sûr.

0 votes

Oui, je fais un peu d'échappement là-dedans, il faut toujours faire attention aux attaques par injection en PHP, mais j'étais trop paresseux pour revenir en arrière et vérifier ce que la commande que j'ai utilisée était.

2 votes

J'ai retiré mon vote parce que vous n'avez pas fourni d'extrait de code de démonstration et que vous avez fait référence à un code qui n'avait pas d'extrait de démonstration sur sa propre page de documentation. Merci de mettre à jour votre réponse et de répondre et si cela fonctionne, je serai heureux d'augmenter votre vote.

15voto

Sudden Def Points 1256

À mon avis, toutes les méthodes de vérification du type MIME sont inutiles.

Disons que vous avez qui devrait avoir MIME-type application/pdf . Les méthodes standard consistent à essayer de trouver quelque chose qui ressemble à un en-tête de PDF ( %PDF- ou quelque chose comme ça) et ils renverront "Ok, il semble que ce soit un fichier PDF" en cas de succès. Mais en fait, cela ne signifie rien du tout. Vous pouvez télécharger un fichier contenant uniquement %PDF-1.4 et il passera le contrôle MIME.

Je veux dire que si le fichier a un type MIME attendu, il passera toujours la vérification du type MIME, sinon le résultat est indéfini.

0 votes

Toute personne qui pense que cette réponse n'est pas correcte, lisez ceci . Une révélation.

0 votes

La vérification du mime n'est pas complètement inutile. Elle est toujours utile dans le cas où l'utilisateur télécharge un fichier non corrompu.

2voto

Oddthinking Points 8946

Je suppose que vous allez avoir une liste blanche fixe de types de fichiers que vous acceptez.

Pour chacun de ces types, vous allez devoir utiliser différentes techniques pour vérifier qu'il s'agit d'exemples valides de ce format.

Deux questions connexes se posent :

  • A-t-il l'air d'être du bon type ? (Pour le JPEG, vous pouvez vérifier les en-têtes, comme vous l'avez mentionné. Pour de nombreux formats basés sur Unix, vous pourriez vérifier le "cookie magique").

  • Est-il réellement un exemple valide de ce type (par exemple, pour tout format de type XML, vous pouvez le valider par rapport à une DTD).

Je pense que, pour chaque format, vous devriez poser des questions distinctes, car la réponse sera très différente pour les PDF par rapport aux fichiers ZIP.

1 votes

Comme indiqué dans la question, getimagesize() fonctionne parfaitement pour les images.

2voto

J'ai utilisé mime_content_type qui est compatible avec PHP 5.2, car je ne peux utiliser ni Fileinfo (il nécessite PHP 5.3) ni system() qui est désactivé par mon fournisseur. Par exemple, je vérifie si un fichier est un fichier texte donc :

if (strcmp(substr(mime_content_type($f),0,4),"text")==0) { ... }

Vous pouvez voir un exemple complet dans mon article "PHP Directory and Subdirectory Listener & File Viewer and Downloader" à l'adresse suivante : http://www.galgani.it/software_repository/index.php

1voto

iZend Points 1

Voici la fonction file_mime_type de iZend :

function file_mime_type($file, $encoding=true) {
    $mime=false;

    if (function_exists('finfo_file')) {
        $finfo = finfo_open(FILEINFO_MIME);
        $mime = finfo_file($finfo, $file);
        finfo_close($finfo);
    }
    else if (substr(PHP_OS, 0, 3) == 'WIN') {
        $mime = mime_content_type($file);
    }
    else {
        $file = escapeshellarg($file);
        $cmd = "file -iL $file";

        exec($cmd, $output, $r);

        if ($r == 0) {
            $mime = substr($output[0], strpos($output[0], ': ')+2);
        }
    }

    if (!$mime) {
        return false;
    }

    if ($encoding) {
        return $mime;
    }

    return substr($mime, 0, strpos($mime, '; '));
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X