1 votes

Comment limiter les types de fichiers dans les téléchargements de fichiers CGI en Perl?

Je suis en train d'utiliser CGI pour permettre à l'utilisateur de télécharger des fichiers. Je veux juste que l'utilisateur puisse télécharger des fichiers .txt ou .csv. Si l'utilisateur télécharge un fichier avec un autre format, je veux être en mesure d'afficher un message d'erreur.

J'ai vu que cela peut être fait en javascript: http://www.codestore.net/store.nsf/unid/DOMM-4Q8H9E

Mais y a-t-il un meilleur moyen d'atteindre cela? Y a-t-il une fonctionnalité en Perl qui permet cela?

6voto

jrockway Points 23734

La clause de non-responsabilité sur le site auquel vous liez est importante :

Remarque : Cela n'est pas entièrement infaillible car les gens peuvent facilement changer l'extension d'un fichier avant de le téléverser, ou faire quelques autres astuces, comme dans le cas du virus "LoveBug".

Si vous voulez vraiment bien faire les choses, laissez l'utilisateur télécharger le fichier, puis utilisez quelque chose comme File::MimeInfo::Magic (ou file(1), l'utilitaire UNIX) pour deviner le type de fichier réel. Si vous n'aimez pas le type de fichier, supprimez le fichier et donnez à l'utilisateur un message d'erreur.

3voto

bobince Points 270740

Je veux juste que l'utilisateur puisse télécharger des fichiers .txt ou .csv.

Cela semble facile, n'est-ce pas? Ce n'est pas le cas. Et même plus.

L'approche simple consiste simplement à vérifier que le fichier se termine par ‘.txt’ ou ‘.csv’ avant de le stocker sur le système de fichiers. Cela devrait faire partie d'une validation beaucoup plus approfondie de ce que le nom de fichier est autorisé à contenir avant de laisser un nom de fichier soumis par l'utilisateur approcher le système de fichiers.

Parce que les règles concernant ce qui peut aller dans un nom de fichier sont complexes sur certaines plateformes (surtout sur Windows), il est généralement préférable de créer votre propre nom de fichier de manière indépendante avec un nom et une extension connue.

Quoi qu'il en soit, il n'y a aucune garantie que le navigateur vous enverra un fichier avec un nom utilisable, et même s'il le fait, il n'y a aucune garantie que ce nom contiendra ‘.txt’ ou ‘.csv’ à la fin, même s'il s'agit d'un fichier texte ou CSV. (Certaines plateformes n'utilisent simplement pas d'extensions pour le typage des fichiers.)

Alors que vous pouvez essayer de renifler le contenu du fichier pour voir de quel type il pourrait s'agir, cela est très peu fiable. Par exemple:

,,,

pourrait être du texte brut, du CSV, de l'HTML, du XML, ou une variété d'autres formats. Il est préférable de donner à l'utilisateur un contrôle explicite pour dire quel type de fichier il télécharge (ou d'utiliser un champ de téléchargement de fichier par type).

Maintenant, voici où cela devient vraiment difficile. Disons que vous avez accepté le téléchargement et l'avez stocké sous /data/mygoodfilename.txt, et que le serveur Web le sert correctement en tant que Content-Type ‘text/plain’. A quoi pensez-vous que le navigateur l'interprète? Du texte brut? Vous seriez bien chanceux.

Le problème est que les navigateurs (principalement IE) ne font pas confiance à votre en-tête Content-Type, et au lieu de cela reniflent le contenu du fichier pour voir s'il ressemble à autre chose. Servez le snippet ci-dessus en tant que texte brut, et IE le traitera joyeusement comme de l'HTML. Ceci peut être un énorme problème, car l'HTML peut inclure des scripts côté client qui prendront le contrôle de l'accès de l'utilisateur au site (une attaque de scriptage intersite).

À ce stade, vous pourriez être tenté de renifler le fichier côté serveur, par exemple en utilisant la commande ‘file’, pour vérifier s'il ne contient pas ‘’. Mais cela est voué à l'échec. La commande ‘file’ ne renifle pas tous les mêmes balises HTML qu'IE et les autres navigateurs reniflent de toute façon différemment. Il est assez facile de préparer un fichier que ‘file’ prétendra ne pas être de l'HTML, mais qu'IE traitera néanmoins comme tel (avec des implications de catastrophe en matière de sécurité).

Les approches de reniflement de contenu telles que ‘file’ ne vous apporteront qu'un faux sentiment de sécurité. C'est un outil de commodité pour deviner grossièrement les types de fichiers et pas une mesure de sécurité efficace.

À ce stade, vos dernières possibilités désespérées sont des choses comme:

  • servir tous les fichiers téléchargés par les utilisateurs à partir d'un nom d'hôte séparé, afin qu'une attaque par injection de script ne puisse pas voler les identifiants de votre site principal;

  • servir tous les fichiers téléchargés par les utilisateurs via un wrapper CGI, en ajoutant l'en-tête ‘Content-Disposition: attachment’ afin que les navigateurs ne tentent pas de les afficher directement;

  • accepter uniquement les téléchargements des utilisateurs de confiance.

2voto

Jeremy Wall Points 10643

Sous Unix, la manière la plus simple de faire comme JRockway l'a suggéré. Si ce n'est pas sous Unix, vos options sont limitées. Vous pouvez examiner l'extension du fichier et examiner le contenu pour vérifier. Je suppose pour votre cas spécifique que vous voulez seulement des fichiers texte de type "* séparés par des valeurs". Donc, un des modules Text::CSV::* peut être utile pour vérifier que le fichier est du type que vous avez demandé.

La sécurité pour cette opération est toute une autre histoire.

0voto

essayez ceci :

$file_name = "file.txt";

$file_cmd = "file \"$file_name"\";

$file_type = `$file_cmd`;

return 0 unless($file_type =~ /(ASCII|text)/i)

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