9
votes

PHP: Comment assainir les noms de fichiers téléchargés?

J'ai une application PHP.

Je permet aux utilisateurs de télécharger des fichiers sur mon application Web.

question : Quelle est la meilleure façon pour moi de désactiver les noms de fichiers des documents téléchargés $ _ fichiers ["nom_fichier]] [" TMP_Name "] dans php? < / p>

mise à jour :

Puis-je prendre un MD5 du nom de fichier téléchargé et l'utiliser comme le nom de fichier nouvellement attribué? Si oui, comment puis-je le faire dans PHP?


5 commentaires

Pouvez-vous donner une définition claire de «sanitize»? Comme pour MySQL? Une URL?


Je télécharge les fichiers sur mon serveur Web. Les fichiers peuvent être des images, des documents, etc. Je ne veux pas de collisions de noms de fichiers. Et je ne veux pas que les gens essaient de télécharger des noms de fichiers qui pourraient être interdits sur mon système de fichiers.


Vous devez également être conscient du type de fichiers que vous leur permettez de télécharger. Vous ne voulez pas que quelqu'un puisse télécharger des choses comme des fichiers HTML / JavaScript.


@Moses: il pourrait vouloir laisser les gens télécharger des fichiers HTML ou EXE. Cependant, il devrait les gérer plus attentivement, par exemple. Ne servez pas HTML comme texte / html mais comme uni / texte.


Sortir de ce que Moïse a dit, vous devez absolument regarder le contenu dans les fichiers. Par exemple, si quelqu'un télécharge un fichier PHP, il pourrait contenir du code malveillant qui permettait d'exploiter des exploits supplémentaires, distribué un virus ou plus. Un moyen d'empêcher que cela soit de vérifier les extensions: PHP, ASP, etc. ne devrait pas être autorisée.


6 Réponses :


2
votes

Je voudrais simplement exécuter une simple regex qui remplace tous les caractères non alphanumériques avec un soulignement (ou simplement enlever ces caractères). Assurez-vous de préserver l'extension du cours.

Si vous voulez aller un peu plus loin, vous pouvez utiliser l'extension MIME Magic MIME pour vous assurer que le fichier est le même format que l'extension indique qu'il est.

EDIT: Pour éviter les collisions de noms de fichiers dans un répertoire, vous pouvez ajouter un MD5 des utilisateurs IP + heure actuelle au nom de fichier.


3 commentaires

Que se passe-t-il s'ils téléchargent 2 documents en même temps?


Ajoutez une entropie supplémentaire, utilisez un compteur pour chaque fichier que vous traitez:


Si $ i est incrémenté pour chaque fichier que vous traitez: nom de fichier $ = $ sanitizéfilename. MD5 ($ _ serveur ["Remote_addr"]. Time (). $ i). $ extension;



-2
votes

Si vous n'êtes pas contre la perte des noms de fichiers, ce que je fais habituellement est de créer un hachage du nom de fichier et de définir le nom de fichier à cela, si tout ce que vous développez a des charges d'images en cours de téléchargement, il aide à éviter les conflits où deux Les noms de fichiers sont nommés semblables et écrases se produisent.

hash('md5', $_FILES["filename"]["tmp_name"]);


12 commentaires

Voulez-vous dire: HASH ('MD5', $ _files ["Nom de fichier"] ["Noms TMP_Name"]) ?


Oui, le premier argument que vous passez est le type de hachage que vous souhaitez créer et que le deuxième argument est la chaîne que vous souhaitez créer le hachage. Php hash - php.net/manual/fr/funcund.hash.php


Je suggérerai également d'ajouter de la pratique de Sam Jours où vous pourriez ajouter l'heure actuelle au nom de fichier avant le hachage, cela créerait un nom de fichier encore plus unique.


Si vous allez «avoir un nom de fichier aléatoire (pseudo) aléatoire», à l'aide du tempnam () -fonction résoudre automatiquement des conditions de course.


Vous auriez certainement besoin d'ajouter quelque chose avant le hachage. Hachage Le nom de fichier seul n'empêche pas les collisions de noms, car le même nom de fichier produira toujours le même hachage.


@jduren, veuillez mettre à jour votre réponse pour être: hash ('MD5', $ _files ["nom de fichier"] ["Noms TMP_Name"]) . Si vous mettez à jour la réponse, je vais marquer est une "acceptée"


@Wrikken Tempnam () crée en fait un nouveau fichier ne l'est-il pas? Utilisation d'une chaîne unique hachée, alors renommer le fichier serait plus idéal.


Non, c'est le nom de fichier TMP PHP utilise lorsqu'un utilisateur télécharge un fichier sur le serveur.


@ user401839 Non, Wrikken a mentionné une fonction Tempnam () dans son commentaire (4ème commentaire sur ma réponse) et je me demande en termes de performance, utilise Tempama () qui crée un nouveau fichier mieux que tout simplement renommer le fichier avec un hachage du nom de fichier d'origine avec le temps ou quelques autres données uniques ajoutées.


@JDUREN: La différence de performance est négligeable, évitant les conditions de course et les noms de fichiers-noms ne sont pas, et avant d'avoir une implémentation solide de ces tempnam () devrait être déjà fait.


@Wikkan Toute chance que vous puissiez fournir un exemple d'installation où vous utiliseriez Tempama () pour faire face à cette question par exemple. Je lis un peu à la page PHP Man de la fonction Tempnam () et je ne vois tout simplement pas comment Tempam est utile dans ce cas. Pour autant que je sache, cela crée un fichier temporaire avec la possibilité de définir un préfixe. Mais cela le crée avec l'extension .TMP renvoie alors le nom de fichier? Créer un nouveau fichier entier pour obtenir une chaîne unique semble un peu trop exclu, mais je peux l'interpréter correctement. Exemple?


(1) Vous allez effectivement utiliser le fichier comme nouveau fichier, la cible du téléchargement (que le fichier n'est pas temporaire comme tempnam vous fera penser, et ne laissez pas Ça vous jette de) (2) Aucun seul télécharger chaque écrase un écrase existant, même si quelqu'un_hash (nom de fichier) est égal (3) NO 2 Téléchargement simultané réclamera le même nom de fichier, même s'ils sont simultanés et entraînent le même hachage . Et oui, les chances pour (2) ou (3) sont minces, cependant, étant donné une combinaison de suffisamment de visiteurs et de temps, cela se produira un jour, puis vous êtes heureux que vous soyez codé sans problème.



5
votes

Je parie que vous stockez également des informations sur le fichier dans la base de données. Si tel est correct, vous pouvez utiliser la touche principale (ID) sous forme de nom de fichier sur votre serveur et conservez le nom de fichier d'origine dans la base de données. Cela vous donne une plus grande flexibilité, car vous pouvez manipuler les métadonnées sans renommer le fichier réel.


0 commentaires

2
votes

Pour éviter que la collision du nom de fichier, vérifiez si le nom de fichier donné ou généré n'existe pas déjà: xxx

qui vous donne 100% sûr que le nom de fichier est unique. L'utilisation de MD5 (ou de tout autre algorithme de hachage) vous assure que le nom de fichier est sécurisé - et facile à manipuler.


8 commentaires

Cela n'a aucun sens. Vous prenez le MD5 de la fonction UNIQID. Pourquoi?


Ce n'est que l'exemple. Vous pouvez utiliser le nom de fichier d'origine, etc. Le point est que vous devez vérifier en boucle si le nom de fichier généré est déjà utilisé. Si oui régénère le nom de fichier.


Prendre MD5 () de Uniqid () n'a aucun sens. Prendre MD5 () du nom de fichier d'origine (c'est-à-dire une valeur constante) dans une boucle réduite encore moins de sens. :-)


Bien sûr, la prise de MD5 de Uniqid a du sens! Uniqid est très longue chaîne contenant des tirets, MD5 le convertit à la séquence de caractères alphanumériques, qui est beaucoup plus agréable à voir. Même prendre MD5 de temps (). $ nom de fichier fait beaucoup de sens - vous générez des noms de fichiers alphanumériques garantis pour être unique!


@CROZIN Désolé pour le nécroposting, mais pourquoi pas MD5 (heure ()), mais MD5 (UNIQID ())? Je comprends que c'est peut-être une question de goût, mais de toute façon?


TIME () a une deuxième résolution, tandis que Uniqid () (qui utilise microtime () ) a 1 résolutioine Miliseconde. Cela signifie que si vous utilisiez heure () en cas de collision, votre boucle ferait la même tâche pendant 1 seconde - ce serait inutile.


Il suffit de lire à travers ce fil i'v devenir plus intelligent. Je ne fais pas attention à de tels détails plus fins, car je remarque la différence de performance temporelle entre UNIQID () et le temps (). La prochaine fois au lieu de simplement aller avec la réponse classée la plus élevée, je vais lire toutes les réponses et les commentaires suivants.


@ wyz1 Vous avez peut-être mal compris le commentaire de Crozin (ou j'ai mal compris le vôtre: p). La différence entre le temps () et UNIQID () n'est pas une question de performance mais une question de précision. Avec le temps (), vous avez des duplicats si deux fichiers sont téléchargés dans la même seconde. Avec UNIQID (), vous avez des doublons uniquement si deux fichiers sont téléchargés dans le même 1 / 1000000ème d'une seconde. En outre, UNIQID () a un paramètre facultatif pour ajouter plus d'entropie au résultat et le rendre encore plus sûr.



0
votes

Au lieu de désinfecter des noms de fichiers spécifiés par l'utilisateur, utilisez tout autre identifiant unique pour cette photo et stockez cela comme nom de fichier. Je préfère utiliser les ID utilisateur qui sont numériques et toujours uniques.

move_uploaded_file ($ _ Fichiers ["Noms TMP_Name"], "/ home / YourName /".cer user_id));

Vous pouvez ensuite récupérer l'image à partir de n'importe quel endroit (dire, S3 ou même votre propre serveur) en connaissant simplement l'ID de l'utilisateur. Vous n'avez même pas besoin d'un attribut dans votre base de données pour stocker l'URL d'image.


1 commentaires

Que se passe-t-il lorsque l'utilisateur doit télécharger plusieurs fichiers?



1
votes

CIAO, cette fonction supprime également tous les points, puis je crée la chaîne propre avec l'extension.

function sanitaze_upload_file($data)
{
    $imgName   = $data;
    $indexOFF  = strrpos($imgName, '.');
    $nameFile  = substr($imgName, 0,$indexOFF);
    $extension = substr($imgName, $indexOFF);
    $clean     = preg_replace("([^\w\s\d\-_~,;\[\]\(\)])", "", 
    $nameFile);
    $NAMEFILE  = str_replace(' ', '', $clean).$extension;
    return $NAMEFILE;
}


1 commentaires

Combien de tests cette fonction a-t-il été via? Puis-je simplement copier et coller cela dans mon code?