Empêcher l'upload de gros fichiers?

noren

WRInaute accro
Salut


Le fichier quelque soit sa taille (dans la limite du php.ini) est toujours uploadé sur le serveur (fichier temporaire). Logique.
Malheureusement si un utilisateur upload un fichier de plusieurs Mo, ca peut vite patiner, voir même planter le script.

Même avec ceci :

Code:
<input type="hidden" name="MAX_FILE_SIZE" value="200000">

Et ceci :

Code:
if(filesize($file['tmp_name']) > $this->maxSize)

N'y a t-il pas des risques de déni de service? (surtout si on tombe sur un utilisateur malintentionné qui ferait plusieurs upload simultanés)

N'y a t-il aucun moyen directement côté client d’empêcher l'upload si la taille du fichier dépasse celle autorisée? Ceci afin d'éviter un upload inutile.

Si je comprend bien lorsqu'on envoi notre formulaire POST, le fichier est d'abord Uploadé avant que l'on puisse faire le moindre contrôle.

je pensais que MAX_FILE_SIZE évitait ça mais en fait non, le fichier est quand même envoyé sur le serveur.

Il me semble qu'avec le javascript c’est également impossible non? Pour des raisons de sécurité on ne peut pas traiter les fichiers côté client, exact?

Y aurait-il une solution pour éviter éventuellement des plantages du serveur, ou éviter que l'utilisateur attende des plombes pour rien?

J'avais pensé utiliser ceci :

ini_set('upload_max_filesize', '200000');
ini_set('post_max_size', '200000');

Malheureusement c’est impossible à cause de ceci : PHP_INI_PERDIR

Après j'ai pensé au .htaccess, malheureusement on dirait bien qu'avec les nouvelles offres d'OVH et le fichier .ovhconfig, on ne peut plus utiliser setEnv dans le .htaccess (du moins ca ne sert à rien)
 

spout

WRInaute accro
Avec l'input hidden MAX_FILE_SIZE, il faut pas s'y fier, on px le modifier facilement.
http://stackoverflow.com/questions/9153224/how-to-limit-file-upload-ty ... ize-in-php

noren a dit:
N'y a t-il aucun moyen directement côté client d’empêcher l'upload si la taille du fichier dépasse celle autorisée? Ceci afin d'éviter un upload inutile.
Si avec File API: https://developer.mozilla.org/en-US/docs/Using_files_from_web_applications

A voir aussi:
http://www.html5rocks.com/en/tutorials/file/dndfiles/
http://www.dropzonejs.com/
 

noren

WRInaute accro
merci, je vais regarder du côté de l'API, en espérant que ca ne soit pas trop complexe.

Sinon sans cette précaution côté client est-ce que je risques des deni de service?

Petite question, quoi qu'il en soit MAX_FILE_SIZE n'empeche absolument pas l'upload du fichier exact? il ajoute juste une erreur dans $file['error']. Mais le fichier est de toute façon temporairement uploadé.
Au début je pensais que MAX_FILE_SIZE empêchait l'upload côté client. :?
 

noren

WRInaute accro
Oui je trouve aussi.

En fait si je met MAX_FILE_SIZE=10 (donc j'autorise un tres tres petit fichier) , mais que j'essaye d'uploader un fichier de 5Mo, le script va quand même mouliner et attendre que le fichier temporaire soit uploadé. Ca va juste servir a mettre le file error à 2. A ce niveau je ne vois plus trop l’intérêt du MAX_FILE_SIZE.

Après le tmp doit surement rester le temps que le script se termine (normal)

Sinon avec les liens que tu m'as envoyé, j'ai réussi à me dépatouiller un peu (je suis assez nul en javascript) j'ai mis ceci :

Code:
<script>
function updateSize() {
  var nBytes = 0,
      oFiles = document.getElementById("avatarInputFile").files,
      nFiles = oFiles.length;
  for (var nFileId = 0; nFileId < nFiles; nFileId++) {
    nBytes += oFiles[nFileId].size;
  }
  var sOutput = nBytes + " bytes";

   if (nBytes > 200000) {
      document.getElementById("fileSize").innerHTML = "<br>Votre avatar est trop lourd. Il ne doit pas dépasser les 200ko";
      document.getElementById("submitAvatar").disabled = "disabled"; 
   }
 
}
</script>

En gros côté client je vérifie uniquement la taille (pour les extensions, mime etc., côté serveur ça suffira amplement)
Si la taille dépasse celle autorisée je désactive le bouton submit et met un message à l'utilisateur.

Je sais pas si c’est suffisant en tout cas ça devrait éviter que des personnes qui veulent charger de grosses images par erreur attendent des plombes et ça évitera quelques surcharges côté serveur inutiles.

Par contre pour les personnes malintentionnés, de toute facon avec firebug etc. ou juste en désactivant le javascript ils pourront quand même passer outre et uploader de gros fichiers qui passeront aux contrôles côté serveur. Mais on ne peut rien faire pour ca j'imagine, non? même avec l'API FILE du html5 ?

Par mesure de sécurité supplémentaire j’interdis plus de x tentatives d'upload par jour. Je stocke le nombre de tentatives dans un fichier. J'utilise également un token à mon formulaire pour éviter l'utilisation de celui ci à l’extérieur du site.
 

spout

WRInaute accro
Concernant le token, look la technique "CSRF protection". Ça permet d'éviter qu'on submit d'autres champs non voulus.
 

noren

WRInaute accro
Oui ça c’est bon pour le token. je contrôle le token, sa date de validité (via sessions) et également le referer.
J'ai même un champ caché qui ne doit pas être rempli. :)

Si je résume ma sécurité :

- Nombre de tentatives d'upload limité
- Token (controle token, date et referer)
- Champ caché qui doit resté vide
- Et je peux également vérifier qu'il n'y est pas 2 upload trop rapprochés de x secondes ou minutes
- Je renomme le fichier

Côté serveur :

- test de l’extension
- test du mime via fileinfo et également avec getimagesize
- test de la taille (fonction filesize())
- Je vérifie également que les noms de fichiers ne comportent pas le mot php et ne contiennent pas de NULL bytes (\0)
- et une fois le move_upload effectué je tente de redimensionnes l'image. Si j'ai une erreur je la supprime.

Normalement il me restait à empêcher l'envoi de gros fichiers aux serveurs. Mais d'après tout ce que j'ai pu lire il n'y a donc pas de solution miracle. ça reste des solutions côté clients facilement détournables pour tout utilisateur qui chercherait à détourner le script.
 

Discussions similaires

Haut