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.