2009-03-10 8 views
8

Lorsqu'un utilisateur télécharge un fichier, il est remplacé au hasard par le téléchargement d'un autre utilisateur, j'ai finalement retrouvé le problème en PHP et le nom du fichier tmp en cours de réutilisation. Y'a t'il un moyen d'arranger cela? Y a-t-il un moyen de faire de meilleurs noms aléatoires? Il semble se dégrader au fil du temps, comme dans le nom de fichier aléatoire, la graine devient plus faible? Ceci est sur PHP 5.2.8 et FreeBSD 7.0Noms de fichiers temporaires PHP pour les téléchargements en conflit

Voici un journal montrant comment le même nom de fichier tmp s'utilisé et est remplacé par un autre téléchargement: http://pastebin.com/m65790440

Toute aide est très appréciée. J'ai essayé de réparer cela pendant plus de 4 mois et a empiré avec le temps. Je vous remercie.

EDIT: Gardez à l'esprit que ce n'est pas un problème de code PHP, cela arrive avant qu'il n'atteigne un code PHP, le fichier reçu via $ _FILES ['nom'] ['tmp_name'] est incorrect quand il est reçu et il a été retracé qu'il est écrasé avec le téléchargement de quelqu'un d'autre avant qu'il n'atteigne le script de traitement de téléchargement

+0

C'est votre tmp dir c'est le problème ou le dossier que vous copiez/déplacer le fichier? – Greg

+0

Je rencontre le même problème avec Freebsd 8 et PHP 5.3. Pour reproduire j'ai un script de téléchargement très simple. Pour 5 tests, il est très probable qu'il y ait une collision. C'est vraiment mauvais. Je n'ai pas encore d'idées par où commencer. Ce problème est également difficile pour Google, comme mentionné ci-dessus. –

Répondre

-1

Je recommanderais d'utiliser un générateur de GUID pour le nom de fichier vu que vous en avez tellement.

+0

Existe-t-il un moyen de contourner la façon dont les fichiers PHP sont importés? dès maintenant, php utilise un schéma 'phpxxxxx' – mrmanman

2

Est-ce que PHP fonctionne sous Apache, comme mod_php?

Vous pouvez essayer de create a per-process temporary upload directory dont le nom contient votre php getmypid(), puis ini_set votre processus PHP upload_tmp_dir à ce répertoire. Cela ne fonctionnera pas si un nouveau processus php est généré pour chaque requête.

+0

Existe-t-il un moyen de contourner la manière dont les fichiers PHP sont importés? – mrmanman

+0

non, mais vous pouvez remplacer (au moment de l'exécution) le répertoire temporaire dans lequel les fichiers temporaires sont placés – vladr

0

Déplacez vos fichiers dans un répertoire utilisateur après leur téléchargement. Ces fichiers temporaires doivent être supprimés.

+0

Ceci est le correctif approprié. Les fichiers de téléchargement temporaires de PHP sont uniquement destinés à rester là où ils sont pendant la durée nécessaire à votre script de traitement pour les déplacer vers l'endroit où ils se trouvent réellement. – chaos

+0

À un certain point, la politique de PHP est devenue supprimer les fichiers temporaires à la fin de la requête si vous ne les avez pas déplacés/renommés, ainsi votre mécanisme actuel entier sera également cassé si vous mettez à jour cette version. – chaos

+0

Ils sont déplacés. Le fichier que le script de traitement de téléchargement de PHP reçoit de $ _FILES ['nom'] ['tmp_name'] est faux pour commencer – mrmanman

4

Il semble que quelque chose ne va vraiment pas avec votre installation de PHP ou n'importe quel appel système PHP utilise en interne pour générer les noms de fichiers aléatoires (probablement tempnam).

Pour tous les autres: PHP gère les fichiers téléchargés en interne avant que le code utilisateur ne soit traité. Ces noms sont stockés dans $_FILES['file']['tmp_name'] (où 'fichier' est le nom (cité) de l'élément d'entrée de fichier sur le formulaire).

+0

Oui je crois que vous avez raison, maintenant je dois trouver comment le réparer = B – mrmanman

+0

I ' J'ai vu si je pouvais trouver quelque chose sur Google, mais je n'ai pas. Le problème se produit-il toujours si vous définissez upload_tmp_dir dans un répertoire différent? – Powerlord

+0

Ouais vient de le tester et le problème survient quand le fichier upload_tmp_dir est différent, est-ce que "noatime" défini sur la partition/var (où les fichiers sont téléchargés) a un effet sur cela? – mrmanman

3

Après avoir chassé le code correspondant jusqu'à _gettemp dans l'implémentation de la libc de FreeBSD 7, je ne comprends pas comment le contenu du fichier tmp_name pourrait être invalide. (Pour le tracer, vous pouvez télécharger une copie de PHP 5.2.8 et lire main/rfc1867.c - ligne 1018 appels dans main/php_open_temporary_file.c, la fonction commençant à la ligne 227, qui fait son travail principal dans la fonction à partir de la ligne 97, qui, cependant, est essentiellement juste un wrapper pour mkstemp sur votre système, qui se trouve dans le FreeBSD libc implementation sur la ligne 66 (lié), qui utilise _gettemp (même que ci-dessus) pour générer réellement le nom de fichier aléatoire.Parmi les the manpage for mkstemp mentionne dans la section BOGUES que le arc4random() function est peut être une possibilité que 2 demandes simultanées entrent dans la section de code critique et retournent le même tmp_name - Je sais trop peu sur la façon dont Apache fonctionne avec mod_php ou php-cgi pour y commenter (bien que l'utilisation de FastCGI/php -cgi pourrait fonctionner - je ne peux pas commenter avec succès sur ceci en ce moment).Cependant, si vous n'avez pas l'impression que le fichier tmp_name est lui-même invalide, mais qu'il entre en collision avec d'autres fichiers téléchargés (par exemple, si vous utilisez la partie filename de tmp_name comme seule source d'unicité dans le nom de fichier stocké), vous pourriez être confronté à des collisions dues à birthday paradox. En another question vous mentionnez avoir quelque 5.000.000 de fichiers à déplacer, et en still another question vous mentionnez recevoir 30-40k téléchargements par jour. Cela me frappe comme une situation principale pour une collision paradoxe anniversaire. Le mktemp man page mentionne que (si on utilise six 'Xs' comme PHP) il y a 56.800.235.584 noms de fichiers possibles (62 ** 6, ou 62 ** n où n = nombre de 'Xs', etc). Cependant, étant donné que vous avez plus de 5 millions de fichiers, la probabilité d'une collision est approximately 100% (une autre heuristique suggère que vous avez déjà déjà rencontré un ordre de 220 collisions, if ((fichiers * (fichiers-1))/2)/(62 ** 6) signifie n'importe quoi, où les fichiers = 5.000.000). Si c'est le problème que vous rencontrez (probable, si ne pas ajouter d'entropie supplémentaire au nom de fichier téléchargé), vous pouvez essayer quelque chose comme move_uploaded_file($file['tmp_name'], UPLOADS.sha1(mt_rand().$file['tmp_name']).strrchr($file['name'], '.')) - l'idée étant d'ajouter plus de caractère aléatoire au nom de fichier aléatoire, empêchant les collisions. Une alternative pourrait être d'ajouter deux X supplémentaires à la ligne 134 de main/php_open_temporary_file.c et de recompiler.

Questions connexes