Membres


Pas encore membre ?
inscrivez-vous ici

Connexion :
Login
Code
Mot de passe perdu ?
Liste des membres

Upload PHP sécurisé - votre avis ?

Upload PHP sécurisé - votre avis ?


Upload PHP sécurisé - votre avis ?     Posté le 28/09/2007 à 17:49
Sky
Administrateur
sky
Site perso
4102 posts
Inscrit le : 13/08/2003
Bonjour à tous

après plusieurs demande, me suis décider à faire quelquechose qui soit un peut plus sécurisé que les uploads "traditionels".

Je voudrai savoir ce que vous en pensez.

A savoir : on peut activé ou désactivé les liens url rewrité qui permette une meilleur compatibilité avec Internet Explorer.



1) créer un répertoire pour mettres les fichiers suivants

2) les fichiers :
- index.php
<?php
include('./config.php');

if(!
$_POST)
{
?>

  <b>Uploadez un fichier</b>
  <form action="" enctype="multipart/form-data" method="post" name="post" onsubmit="return checkForm(this)">
    Votre fichier : <input type="file" name="fichier" tabindex="1" size="40" /> <input type="submit" accesskey="s" tabindex="2" name="envoyer" value="Ok" />
  </form>
  
<?php
}else{

  if(isset(
$_FILES['fichier']['tmp_name']) && isset($_FILES['fichier']['name']) && $_FILES['fichier']['name'] != '')
  {
    
$tmp_file $_FILES['fichier']['tmp_name'];
    
$erreurs '';
    
    
//on test si l'upload a reussi
    
if(!is_uploaded_file($tmp_file))
      exit(
'Une erreurs est survenu lors de l\'upload !');
  
    
// on vérifie maintenant l'extension
    
$type_file $_FILES['fichier']['type'];
    if(empty(
$type_file))
      exit(
"Extension non valide");
    
    if(empty(
$_FILES['fichier']['name']))
      exit(
"Nom de fichier trop court");
  
    
// on copie le fichier dans le dossier de destination
    
$name_file md5(mktime()).'_'.clean_file_name($_FILES['fichier']['name']);
    
    
//on verifie que le fichier ne contient pas trop de sales caracteres
    
if(preg_match('#[\x00-\x1F\x7F-\x9F/\\\\]#'$name_file))
      exit(
"Nom de fichier non valide");
    
    
//on bouge le fichier du repertoire temporaire a notre repertoire cache
    
if(!move_uploaded_file($tmp_file$_rep_secret '/' $name_file))
      exit(
"Impossible de copier le fichier");
    else
    {
    
      
$date mktime();
      
$ip $_SERVER['REMOTE_ADDR'];
      
$requete "INSERT INTO $_sqltable SET file='$name_file', ip='$ip', date='$date'";
      if(
mysql_query($requete))
      {
        
// ok, on a mis le fichier dans la base. On recupere le dernier Identifiant et on affiche les liens et autre infos selon l'extension du fichier.
        
$last_id mysql_insert_id();
        
$ext get_file_ext($name_file);
        
        
//si c'est une image avec une extension valide : 
        
$miniature '';
        if(
$_array_extok[$ext] == $ext && !empty($ext) && valide_img($_rep_secret.'/'.$name_file))
          if(
$_urlrewriting == 1)
            
$miniature '<p>Le lien pour voir l\'image est : <a href="'.$_votre_site.'/'.$_rep_myphpupoload.'/voir_'.$last_id.'.'.$ext.'">'.$_votre_site.'/'.$_rep_myphpupoload.'/voir_'.$last_id.'.'.$ext.'</a></p>';
          else
            
$miniature '<p>Le lien pour voir l\'image est : <a href="'.$_votre_site.'/'.$_rep_myphpupoload.'/view.php?id='.$last_id.'">'.$_votre_site.'/'.$_rep_myphpupoload.'/view.php?id='.$last_id.'</a></p>';
        
        
// lien pour telecharger : 
        
if($_urlrewriting == 1)
          
$download '<p>Le lien pour télécharger le fichier est : <a href="'.$_votre_site.'/'.$_rep_myphpupoload.'/dld_'.$last_id.'">'.$_votre_site.'/'.$_rep_myphpupoload.'/dld_'.$last_id.'</a></p>';
        else
          
$download '<p>Le lien pour télécharger le fichier est : <a href="'.$_votre_site.'/'.$_rep_myphpupoload.'/dld.php?id='.$last_id.'">'.$_votre_site.'/'.$_rep_myphpupoload.'/dld.php?id='.$last_id.'</a></p>';
        
        echo 
'
        <p>Upload réussi !</p>
        '
.$download.'
        '
.$miniature.'
        <p><a href="./">retour</a></p>'
;
      
      }
      else
        echo 
'Une erreurs est survenu lors de la requete MySQL ...';
      
    }
    
    
  }
  
}
?>

- dld.php :
<?php
include('./config.php');

$id = (int)$_GET['id'];

$requete "SELECT * FROM $_sqltable WHERE id='$id'";
$sql mysql_query($requete);
$nbr mysql_num_rows($sql);

if(
$nbr == 0)
  exit(
'Fichier invalide');
else
{
  
$post mysql_fetch_array($sql);
  
$fichier $post['file'];
}

$fichier htmlentities(str_replace('./','',$fichier), ENT_QUOTES);
$urlFichier $_rep_secret.'/'.$fichier;


// on verifie que y'a pas trop de mauvaise chose dans le nom de fichier ... au cas ou !
if(eregi('\.\./',$fichier))
  exit;
if(
$fichier=="/")
  exit;

// le nom de fichier
$filename substr($fichier,30);

switch(
strrchr(basename($fichier), ".")) {
  case 
".gz"$type "application/x-gzip"; break;
  case 
".tgz"$type "application/x-gzip"; break;
  case 
".zip"$type "application/zip"; break;
  case 
".pdf"$type "application/pdf"; break;
  case 
".psd"$type "application/psd"; break;
  case 
".eps"$type "application/eps"; break;
  case 
".png"$type "image/png"; break;
  case 
".gif"$type "image/gif"; break;
  case 
".jpg"$type "image/jpeg"; break;
  case 
".txt"$type "text/plain"; break;
  case 
".htm"$type "text/html"; break;
  case 
".html"$type "text/html"; break;
  default: 
$type "application/octet-stream"; break;
}

header("Content-disposition: attachment; filename=".$filename);
header("Content-Type: application/force-download");
header("Content-Transfer-Encoding: $type\n");
header("Content-Length: ".filesize($urlFichier));
header("Pragma: no-cache");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0, public");
header("Expires: 0");

readfile($urlFichier);
exit();
?>

- config.php :
<?php
/* par Gunning sky */
/* www.graphiks.net */
/* septembre 2007 */


// connexion MySQL
$hoste 'localhost';
$usere 'Utilisateur';
$passe 'MotDePasse';
$dbe 'NomDeLaBase';
mysql_connect($hoste,$usere,$passe) or die ('Erreur : '.mysql_error());
mysql_select_db($dbe) or die ('Erreur :'.mysql_error());


// quelques variables a changer selon vos besoins
// celui est ABSOLUMENT a changer. Je vous conseil un nom de repertoire vraiment complexe genre : 4578gopidsfsfq
$_rep_secret '';
$_rep_secret 'dossier_a_fichiers';
$_votre_site 'http://www.votresite.com';
$_rep_myphpupoload 'myPHPupload';
$_sqltable 'myphpupload';
$_urlrewriting 1;
$_img_maxlargeur 700;
$_array_extok = array('jpg'=>'jpg''jpeg'=>'jpeg''gif'=>'gif''png'=>'png');


// et quelques fonctions sympa
function get_file_ext($file)
{
  
$ext substr(strtolower(strrchr(basename($file), ".")), 1);
  return 
$ext;
}

function 
valide_img($file)
{
  list(
$width$height$type$attr) = getimagesize($file);
  if(
$width && $height 0)
    return 
true;
  else
    return 
false;
}

function 
clean_file_name($var)
{
  
$var=strtr($var,"ÀÁÂÃÄÅàáâãäåÒÓÔÕÖØòóôõöøÈÉÊËéèêëÇçÌÍÎÏìíîïÙÚÛÜùúûüÿÑñ","AAAAAAaaaaaaOOOOOOooooooEEEEeeeeCcIIIIiiiiUUUUuuuuyNn");
  
$var=strtolower($var);
  
$var=str_replace("'","_",$var);
  
$var=str_replace("\"","_",$var);
  
$var=str_replace(" ","_",$var);
  
$var=str_replace("__","_",$var);
  
$var=str_replace("__","_",$var);
  
$var=eregi_replace("[^a-z0-9\_\-\.]","",$var);
  
$var rtrim($var,'_');
  
$var ltrim($var,'_');
  return 
$var;
}
?>

- view.php :
<?php
include('./config.php');

$id = (int)$_GET['id'];

$requete "SELECT * FROM $_sqltable WHERE id='$id'";
$sql mysql_query($requete);
$nbr mysql_num_rows($sql);

if(
$nbr == 0)
  exit(
'Fichier invalide');
else
{
  
$post mysql_fetch_array($sql);
  
$fichier $post['file'];
}

$fichier htmlentities(str_replace('./','',$fichier), ENT_QUOTES);
$ext get_file_ext($fichier);

switch(
$ext)
{
  case 
'jpg':
  case 
'jpeg':
    
header('Content-type:image/jpg');
    if(!
file_exists($_rep_secret.'/tmp_'.$fichier))
    {
      
$image $_rep_secret.'/'.$fichier;
      
$src_im ImageCreateFromJpeg($image);
      
$size GetImageSize($image);
      
$src_w $size[0];
      
$src_h $size[1];
      
      if(
$src_w $_img_maxlargeur)
      {
        
$dst_w $_img_maxlargeur;
        
$dst_h round(($dst_w $src_w) * $src_h);
      }
      else
      {
        
$dst_w $size[0];
        
$dst_h $size[1];
      }

      
$dst_im ImageCreateTrueColor($dst_w,$dst_h);
      
ImageCopyResampled($dst_im,$src_im,0,0,0,0,$dst_w,$dst_h,$src_w,$src_h);
      
imageJpeg($dst_im,$_rep_secret.'/tmp_'.$fichier);
    }

    
readfile($_rep_secret.'/tmp_'.$fichier);
    exit();
  break;
  
  case 
'gif':
    
header('Content-type:image/gif');
    if(!
file_exists($_rep_secret.'/tmp_'.$fichier))
    {
      
$image $_rep_secret.'/'.$fichier;
      
$src_im ImageCreateFromGif($image);
      
$size GetImageSize($image);
      
$src_w $size[0];
      
$src_h $size[1];
      
      if(
$src_w $_img_maxlargeur)
      {
        
$dst_w $_img_maxlargeur;
        
$dst_h round(($dst_w $src_w) * $src_h);
      }
      else
      {
        
$dst_w $size[0];
        
$dst_h $size[1];
      }
      
      
$dst_im ImageCreateTrueColor($dst_w,$dst_h);
      
ImageCopyResampled($dst_im,$src_im,0,0,0,0,$dst_w,$dst_h,$src_w,$src_h);
      
imageGif($dst_im,$_rep_secret.'/tmp_'.$fichier);
    }

    
readfile($_rep_secret.'/tmp_'.$fichier);
    exit();
  break;
  
  case 
'png':
    
header('Content-type:image/png');
    if(!
file_exists($_rep_secret.'/tmp_'.$fichier))
    {
      
$image $_rep_secret.'/'.$fichier;
      
$src_im ImageCreateFromPng($image);
      
$size GetImageSize($image);
      
$src_w $size[0];
      
$src_h $size[1];
      
      if(
$src_w $_img_maxlargeur)
      {
        
$dst_w $_img_maxlargeur;
        
$dst_h round(($dst_w $src_w) * $src_h);
      }
      else
      {
        
$dst_w $size[0];
        
$dst_h $size[1];
      }
      
      
$dst_im ImageCreateTrueColor($dst_w,$dst_h);
      
ImageCopyResampled($dst_im,$src_im,0,0,0,0,$dst_w,$dst_h,$src_w,$src_h);
      
imagePng($dst_im,$_rep_secret.'/tmp_'.$fichier);
    }

    
readfile($_rep_secret.'/tmp_'.$fichier);
    exit();
  break;
}


- la structure mysql :
CREATE TABLE `myphpupload` (
  `id` mediumint(7) NOT NULL auto_increment,
  `date` int(10) NOT NULL default '0',
  `file` varchar(255) NOT NULL default '',
  `ip` varchar(40) NOT NULL default '',
  PRIMARY KEY  (`id`),
  KEY `date` (`date`)
) ENGINE=MyISAM

- .htaccess :
Options +FollowSymlinks
RewriteEngine on

#generique : page accueil de chaque module
RewriteRule ^voir_([0-9]+).jpg$ view.php?id=$1 [L]
RewriteRule ^voir_([0-9]+).jpeg$ view.php?id=$1 [L]
RewriteRule ^voir_([0-9]+).gif$ view.php?id=$1 [L]
RewriteRule ^voir_([0-9]+).png$ view.php?id=$1 [L]


RewriteRule ^dld_([0-9]+)$ dld.php?id=$1 [L]



V'la.
Ceci n'est pas vraiment un script d'upload complet et sécurisé, mais un concept un peut plus évolué que la plupart des upload PHP que l'on peut trouvé par ici.

Je serai ravie si vous pouviez le tester et m'en donner des nouvelles ... et améliorer la sécurité si possible.

Sky

________________________
Graphiks : Cours PHP
Image
=> à quoi sert internet explorer ?
=> à télécharger firefox
 
Réponse à : Upload PHP sécurisé - votre avis ?     Posté le 28/09/2007 à 17:58
sky
Administrateur
Avatar
Site perso
4102 posts
Inscrit le : 13/08/2003
explications sur le système d'upload en PHP

index.php permet d'upload les fichiers, il donne un crypter en md5 basé sur un mktime et ensuite génère 1 lien pour télécharger le fichier et 1 lien pour afficher l'image si le fichier est une image. (jpg, gif et png supporté pour l'instant)

dld.php : permet de télécharger le fichier en tenant compte de l'id qui passe dans l'url.

view.php : permet d'afficher une image selon l'id qui passe dans l'url. (il manque quelques vérifications ici peut être pour être sur que le fichier manipuler est une image)

config.php : permet de personalisé un peut le mini script sans trop changer le code PHP

.htaccess : se fichier sert à rendre les url un peut plus sympa pour que IE les accepte sans bronché mais aussi pour ajouter une petite couche de sécurité pour les personne qui sont capable de modifier le fichier.

Bon, j'attend vos commentaire sur se système d'upload PHP sécurisé.


Ps : le but du script est de fournir un lien vers un fichier sans lui donner la location exact du fichir sur le serveur. (dld.php?id=1 au lieu de /undossier/uneimage.jpg)

Lors de l'upload, l'image est placé dans un répertoire et renommé. Le nom des fichiers étant : md5(mktime()).'_'.$nomdufichier;
De cette façon, on génère un nom de fichier dur à trouvé même si on toruve le répertoire dans lesquel ils est stocké.

Sky

_______________________
Graphiks : Cours PHP
Image
=> à quoi sert internet explorer ?
=> à télécharger firefox
 
Réponse à : Upload PHP sécurisé - votre avis ?     Posté le 28/09/2007 à 18:19
sky
Administrateur
Avatar
Site perso
4102 posts
Inscrit le : 13/08/2003
Pour télécharger directement tous les fichiers myPHPupload : http://www.graphiks.net/telecharger/myPHPupload.zip

_______________________
Graphiks : Cours PHP
Image
=> à quoi sert internet explorer ?
=> à télécharger firefox
 
Réponse à : Upload PHP sécurisé - votre avis ?     Posté le 1/10/2007 à 12:15
sky
Administrateur
Avatar
Site perso
4102 posts
Inscrit le : 13/08/2003
je le remonte pour infos smiley

un autre avantage c'est de laissé uploader n'importe quelle extension de fichier.

faudray ajouter quelques correction de bugs, un système de cache simple et un pouvoir dire combien de temps un fichier reste en téléchargement.

_______________________
Graphiks : Cours PHP
Image
=> à quoi sert internet explorer ?
=> à télécharger firefox
 
Réponse à : Upload PHP sécurisé - votre avis ?     Posté le 2/10/2007 à 10:33
sky
Administrateur
Avatar
Site perso
4102 posts
Inscrit le : 13/08/2003
Mise à jours - version myPHPupload 0.2

On peut maintenant :
- definir une date de validite maximal pour les fichiers
- restreindre l'upload a certain extension uniquement

Amélioration :
- meilleurs test de validité d'une image
- plus d'erreurs visible (faudrai juste mettre un error = 0, je le fairai pour la prochaine mise à jours)
- ajout d'un include en header et footer en html pour facilement personalisé le script à votre besoin. (facile à enlever si vous voulez l'intégrer vous même)
- plus de commentaire sur le code PHP et des procédures


Ensuite le flo habituel d'une deuxième relecture des erreurs bete de programmation smiley

Téléchargeable ici : http://www.graphiks.net/telecharger/myPHPupload.zip




A faire :
- au lieu de passé l'"id" dans l'url, se serai mieu de généré une chaine aléatoire basé sur un md5 pour que l'on ne puisse pas retrouvé les fichiers mis en ligne par d'autre personne.

_______________________
Graphiks : Cours PHP
Image
=> à quoi sert internet explorer ?
=> à télécharger firefox
 
Vous n'est pas connecté en temps que membre, parceque j'en ai marre du spam, SEUL les membres peuvent poster des messages sur le forum.

Nous  -  Plan du site  -  Informations légale  -  Contact  -  © Graphiks.net