Home » Programmation » PHP: Uploader des images de façon sécurisée

PHP: Uploader des images de façon sécurisée

Par NazzTazz le 16/06/09 à 17h26 dans Programmation
L'upload d'images en PHP est une action qui peut paraitre triviale mais qui en réalité cache de nombreuses failles de sécurité potentielles dans vos scripts.

En vrac: upload de scripts malintentionnés (backdoors), injection de code php (si une faille include est présente), vol de cookie administrateur (affichage d'une image qui n'en est pas une, un fichier flash par exemple)...

Le code source est en bas de l'article, il est placé sous license libre LGPL donc librement utilisable.

Quelques détails intéressants, en passant:

Le stockage des images est subdivisé en 256 répertoires, pour des raisons de stabilité et de performances. En effet, sous Unix / linux ( avec un systeme de fichier ext3 ) le listage
d'un répertoire ( et donc toute opération sur un fichier qu'il contient ) est rapide si son nombre d'élements directs est inférieur a 2000.

L'extension du fichier n'a que peu d'importance, mais elle est ajoutée quand même, au cas où un visiteur sous Windows sauvegarderait une image sur son disque (en effet Windows se fonde sur l'extension d'un fichier pour en déterminer le type).

Le source

<?php

/**
*   image_upload() - Uploade une image
*
*   @author NazzTazz  <nazztazz@nextgeneration.fr>
*
*   @param  $name   string  Nom du champ upload
*   @param  $path   string  Répertoire destination
*
*   @return         mixed   Le chemin de l'image, ou bool(false) en cas d'erreur
*/

function image_upload($name, $path)
{

    if (!isset($_FILES[$name]))
      return false;

    $newname = sha1(microtime(true));
    $newname = $newname[0].'/'.$newname[1].'/'.$newname;

    if ($_FILES[$name]['error'] != 0)
      return false;

    $dir = dirname($path . $newname);

    if (!file_exists($dir))
      mkdir($dir, 0777, true);

    @move_uploaded_file($_FILES[$name]['tmp_name'], $path . $newname);

    if (!file_exists($path . $newname))
      return false;

    $img_info = @getimagesize($path . $newname);

    if (!$img_info)
    {
      @unlink($path . $newname);
      return false;
    }

    $img_types = array( IMAGETYPE_GIF, IMAGETYPE_JPEG, IMAGETYPE_PNG );
    $exts = array(
      IMAGETYPE_GIF   =>  'gif',
      IMAGETYPE_JPEG  =>  'jpg',
      IMAGETYPE_PNG   =>  'png'
    );

    if (!in_array($img_info[2], $img_types))
    {
      @unlink($path . $newname);
      return false;    
    }

    rename($path . $newname, $path . $newname . '.' . $exts[$img_info[2]]);

    return $path . $newname . '.' . $exts[$img_info[2]];

}
Home » Programmation » PHP: Uploader des images de façon sécurisée