27 votes

Empêcher les personnes de télécharger des fichiers PHP malveillants via des formulaires

J'ai un formulaire de téléchargement créé en php sur mon site Web où les gens peuvent télécharger un fichier zip. Le fichier zip est ensuite extrait et tous les emplacements des fichiers sont ajoutés à une base de données. Le formulaire de téléchargement permet aux utilisateurs de télécharger uniquement des photos. Évidemment, comme les fichiers se trouvent dans le dossier zip, je ne peux pas vérifier quels fichiers sont téléchargés avant que le fichier ne soit extrait. J'ai besoin d'un bout de code qui supprime tous les fichiers qui ne sont pas des formats d'image (.png, .jpeg, etc). J'ai vraiment peur que les gens puissent télécharger des fichiers php malveillants, un gros risque de sécurité ! Je dois également faire attention aux personnes qui modifient les extensions des fichiers php pour tenter de contourner ce dispositif de sécurité.

Voici le script original que j'ai utilisé http://net.tutsplus.com/videos/screencasts/how-to-open-zip-files-with-php/

C'est le code qui extrait réellement le fichier .zip :

function openZip($file_to_open) {
    global $target;

    $zip = new ZipArchive();
    $x = $zip->open($file_to_open);
    if($x === true) {
        $zip->extractTo($target);
        $zip->close();

        unlink($file_to_open);
    } else {
        die("There was a problem. Please try again!");
    }
}

Merci, Ben.

61voto

bobince Points 270740

J'ai vraiment peur que les gens puissent télécharger des fichiers php malveillants, un gros risque de sécurité !

La pointe de l'iceberg !

je dois également être conscient que des personnes modifient les extensions des fichiers php pour tenter de contourner cette fonction de sécurité.

En général, changer les extensions empêchera PHP d'interpréter ces fichiers comme des scripts. Mais ce n'est pas le seul problème. Il y a d'autres choses que '...php' qui peuvent endommager le côté serveur ; '.htaccess' et les fichiers avec le bit X activé sont les plus évidents, mais pas les seuls dont vous devez vous soucier. Même en ignorant les problèmes côté serveur, il y a un énorme problème côté client.

Par exemple, si quelqu'un peut télécharger un fichier ".html", il peut y inclure une balise <script> qui détourne la session d'un utilisateur tiers et supprime tous ses fichiers téléchargés ou modifie son mot de passe ou autre. Il s'agit d'une attaque cross-site-scripting (XSS) classique.

De plus, grâce aux comportements de "reniflage de contenu" de certains navigateurs (principalement IE), un fichier téléchargé en tant que ".gif" peut en fait contenir du HTML malveillant comme celui-ci. Si IE voit des indicateurs comme (mais pas seulement) "<html>" au début du fichier, il peut ignorer le "Content-Type" et l'afficher en HTML, ce qui entraîne un XSS.

De plus, il est possible d'élaborer un fichier qui est les deux une image valide que votre analyseur d'images acceptera, y contient du HTML intégré. Plusieurs résultats sont possibles en fonction de la version exacte du navigateur de l'utilisateur et du format exact du fichier image (les JPEG, en particulier, ont un ensemble très variable de formats d'en-tête possibles). Il existe mesures d'atténuation à venir dans IE8, mais cela ne sert à rien pour le moment, et on peut se demander pourquoi ils ne peuvent pas simplement arrêtez de faire du content-sniffing, bande d'idiots MS au lieu de nous imposer des extensions non standard aux en-têtes HTTP qui auraient dû fonctionner dès le départ.

Je tombe à nouveau dans une diatribe. Je vais m'arrêter. Tactiques pour servir les images fournies par les utilisateurs de manière sécurisée :

1 : Ne stockez jamais un fichier sur le système de fichiers de votre serveur en utilisant un nom de fichier issu de la saisie de l'utilisateur. Cela permet d'éviter les bogues et les attaques : les différents systèmes de fichiers ont des règles différentes concernant les caractères autorisés dans un nom de fichier, et il est beaucoup plus difficile que vous ne le pensez de "nettoyer" les noms de fichiers.

Même si vous avez choisi quelque chose de très restrictif comme "seulement des lettres ASCII", vous devez toujours vous inquiéter des noms trop longs, trop courts et réservés : essayez d'enregistrer un fichier avec un nom aussi inoffensif que "com.txt" sur un serveur Windows et regardez votre application tomber en panne. Vous pensez connaître toutes les bizarreries des noms de chemin de tous les systèmes de fichiers sur lesquels votre application pourrait fonctionner ? Vous êtes sûr ?

Au lieu de cela, stockez les détails du fichier (tels que le nom et le type de média) dans la base de données, et utilisez la clé primaire comme nom dans votre filestore (par exemple, "74293.dat"). Vous avez ensuite besoin d'un moyen de les servir avec différents noms de fichiers apparents, comme un téléchargeur script crachant le fichier, un téléchargeur script faisant une redirection interne du serveur web, ou une réécriture d'URL.

2 : Soyez très, très prudent en utilisant ZipArchive. Il y a eu des traversées vulnérabilités dans les extractTo du même type que ceux qui ont affecté la plupart des extracteurs ZIP naïfs basés sur le chemin. De plus, vous vous exposez à des attaques de la part de Bombes ZIP . Le mieux est d'éviter tout risque de mauvais nom de fichier, en passant en revue chaque entrée de fichier dans l'archive (par exemple, en utilisant la commande zip_read/zip_entry_* ) et de vérifier ses détails avant de décompresser manuellement son flux vers un fichier avec un nom et des drapeaux de mode connus, que vous avez généré sans l'aide de l'archive. Ignorez les chemins des dossiers à l'intérieur du ZIP.

3 : Si vous pouvez charger un fichier image et le sauvegarder à nouveau Vous pouvez être raisonnablement certain que les résultats seront propres, surtout si vous les traitez d'une manière ou d'une autre entre-temps (par exemple pour les redimensionner, les mettre en miniature ou ajouter un filigrane). En théorie, il pourrait être possible de créer une image ciblant un compresseur d'image particulier, de sorte que lorsqu'elle est compressée, les résultats ressemblent également à du HTML, mais cela me semble être une attaque très difficile.

4 : Si vous pouvez vous en sortir en proposant toutes vos images en téléchargement (c'est-à-dire en utilisant 'Content-Disposition : attachment' dans un script de téléchargement), vous êtes probablement en sécurité. Mais cela pourrait être un trop grand désagrément pour les utilisateurs. Cela peut fonctionner en tandem avec (3), cependant, en servant des images plus petites et traitées en ligne et en ayant les images originales de meilleure qualité disponibles uniquement en téléchargement.

5 : Si vous devez servir des images non modifiées en ligne, vous pouvez éliminer le risque de cross-site-scripting en les servant à partir d'un domaine différent. Par exemple, utilisez "images.exemple.com" pour les images non fiables et "www.example.com" pour le site principal qui contient toute la logique. Veillez à ce que les cookies soient limités au bon hôte virtuel et à ce que les hôtes virtuels soient configurés de manière à ne répondre qu'à leurs noms propres (voir aussi : attaques par rebond DNS). C'est ce que font de nombreux services de messagerie Web.

En résumé, le contenu médiatique soumis par les utilisateurs est un problème.

En résumé du résumé, AAAARRRRRRGGHHH.

ETA re commentaire :

En haut de la page, vous parlez de "fichiers dont le bit X est activé", qu'entendez-vous par là ?

Je ne peux pas parler pour ZipArchive.extractTo() Je ne l'ai pas testé, mais de nombreux extracteurs, lorsqu'on leur demande de vider des fichiers d'une archive, recréent [certains] des drapeaux de mode de fichier Unix associés à chaque fichier (si l'archive a été créée sur un Unix et possède donc des drapeaux de mode). Cela peut vous causer des problèmes de permissions si, par exemple, la permission de lecture du propriétaire est manquante. Mais cela peut aussi être un problème de sécurité si votre serveur est compatible avec les CGI : un bit X peut permettre au fichier d'être interprété comme un script et passé à n'importe quel interpréteur script listé dans le hashbang de la première ligne.

Je pensais que le fichier .htaccess devait se trouver dans le répertoire racine principal, n'est-ce pas le cas ?

Cela dépend de la configuration d'Apache, en particulier de la directive AllowOverride. Il est courant pour les hôtes polyvalents d'utiliser AllowOverride pour n'importe quel répertoire.

Que se passerait-il si quelqu'un téléchargeait encore un fichier comme ../var/www/wr_dir/evil.php ?

Je m'attendrais à ce que le premier " " soit éliminé, c'est ce qu'ont fait d'autres outils qui ont souffert de la même vulnérabilité.

Mais je ne ferais toujours pas confiance extractTo() contre une entrée hostile, il y a trop de petites choses bizarres concernant les noms de fichiers et les arborescences de répertoires qui peuvent mal tourner - surtout si vous vous attendez à ce qu'ils fonctionnent sur des serveurs Windows. zip_read() vous permet de contrôler beaucoup plus le processus de désarchivage, et donc l'attaquant beaucoup moins.

15voto

Gumbo Points 279147

Tout d'abord, vous devez interdire tout fichier qui n'a pas une extension de fichier image appropriée. Et ensuite, vous pouvez utiliser la fonction getimagesize fonction pour vérifier si les fichiers sont des fichiers images ordinaires.

Mais en outre, vous devez savoir que certains formats d'image autorisent les commentaires et autres méta-informations. Celles-ci pourraient être utilisées pour du code malveillant, tel que le JavaScript que certains navigateurs exécutent dans certaines circonstances (cf. Reniflage MIME risqué dans Internet Explorer ).

8voto

John Ellinwood Points 6578

Vous ne devriez probablement pas vous fier uniquement à l'extension du nom de fichier, alors. Essayez de faire passer chaque fichier par une bibliothèque d'images pour valider qu'il s'agit bien d'une image.

2voto

Assaf Lavie Points 20181

Je ne vois pas le risque d'avoir des fichiers php renommés dans votre BD... Tant que vous ne les évaluez pas comme des fichiers PHP (ou pas du tout, d'ailleurs), ils ne peuvent pas faire trop de mal, et comme il n'y a pas d'extension .php, le moteur php ne les touchera pas.

Je suppose que vous pourriez aussi chercher dans les fichiers <?php ...

Aussi : supposez le pire concernant les fichiers téléchargés sur votre machine. Renommez le dossier dans lequel vous les enregistrez "virus" et traitez-le en conséquence. Ne le rendez pas public, ne donnez à aucun fichier les droits de lancement (en particulier à l'utilisateur php), etc.

2voto

Saem Points 2415

Vous pouvez également envisager de faire la détection des types de mime avec la bibliothèque suivante :

http://ca.php.net/manual/en/ref.fileinfo.php

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