Sécurité en forçant le téléchargement de .png

Répondre


Cette question est un moyen d’empêcher des soumissions automatisées de formulaires par des robots.
Smileys
:D :) :( :o :shock: :? 8-) :lol: :x :P :oops: :cry: :evil: :twisted: :roll: :wink: :!: :?: :idea: :arrow: :| :mrgreen: =D> #-o =P~ :^o :non: :priere: 8-|
Voir plus de smileys
  Revue du sujet
 

  Étendre la vue Revue du sujet : Sécurité en forçant le téléchargement de .png

Re: Sécurité en forçant le téléchargement de .png

par AB » 07 avr. 2011, 02:14

Attention tu ne vérifie pas le dossier dans le code précédent, tu vérifie juste qu'il existe.
De sorte que si tu avais un dossier protégé par un .htaccess dans lequel tu mettrais par exemple des images .png confidentielles, et bien on pourrait les télécharger !

Re: Sécurité en forçant le téléchargement de .png

par Doubrovski » 06 avr. 2011, 18:58

Merci de votre aide, je pense que le code est assez sécurisé pour le moment !
Vérif du dossier + vérif de l'extension du fichier c'est pas mal.
Bonne soirée

Re: Sécurité en forçant le téléchargement de .png

par AB » 06 avr. 2011, 18:25

Il ne me reste qu'a autoriser ou non les dossiers, mais sur quelle page je devrais mettre cette ligne ?
$dos_autorise = array('photos-arbres','photo-chats', 'photos-chiens');
Si je l'insère sur la page telecharger.php avant la condition qui vérifie le dossier et avant l'envoi du téléchargement, ça ne pose pas problème ? (simple doute, mais je pense que non : sinon la variable ne serait pas transmise à la page telecharger.php)
Bien entendu qu'il faut mettre ça dans telecharger.php, justement pour que ta liste soit indépendante de toute variable transmise.

Re: Sécurité en forçant le téléchargement de .png

par Doubrovski » 06 avr. 2011, 13:52

Merci, j'ai mélangé un peu mon script initial avec celui trouvé ci dessus, et comme tu m'as conseillé j'ai limité l'extension des fichiers téléchargeables à .png
Il ne me reste qu'a autoriser ou non les dossiers, mais sur quelle page je devrais mettre cette ligne ?
$dos_autorise = array('photos-arbres','photo-chats', 'photos-chiens');
Si je l'insère sur la page telecharger.php avant la condition qui vérifie le dossier et avant l'envoi du téléchargement, ça ne pose pas problème ? (simple doute, mais je pense que non : sinon la variable ne serait pas transmise à la page telecharger.php)

Voilà le code actuel :
<?php

/** on récupère le nom du fichier demandé **/
if(isset($_GET['filename']))
$filename = $_GET['filename'];
elseif(isset($_POST['filename']))
$filename = $_POST['filename'];
else
$filename = '';

/** on récupère le nom du dossier demandé **/
if(isset($_GET['filepath']))
$filepath = $_GET['filepath'];
elseif(isset($_POST['filepath']))
$filepath = $_POST['filepath'];
else
$filepath = '';

/** tant qu'a faire évitons les attaques par directory transversal **/
$filename = str_replace(array('../','..\\'),'',$filename);

/** tant qu'a faire évitons les attaques par directory transversal **/
$filepath = str_replace(array('../','..\\'),'',$filepath);

/** la variable est elle vide, le fichier existe ? **/
if(empty($filename))
exit('Aucun fichier s&eacute;lectionn&eacute; !');
elseif(!is_file($filepath.$filename))
exit('Fichier introuvable !');

/** la variable est elle vide, le fichier existe ? **/
if(empty($filepath))
exit('Aucun dossier s&eacute;lectionn&eacute; !');
elseif(!is_dir($filepath))
exit('Dossier introuvable !');

$extensions_ok = array ( ".png");
if (in_array(strtolower(substr($filename, -4)),$extensions_ok))
   {
header("Content-Type: application/force-download" );
header("Content-Transfer-Encoding: image/png\n" );
header("Content-disposition: attachment; filename=$filename" );
header("Content-Length: ".filesize($filepath. $filename));
header("Pragma: no-cache" );
header("Cache-Control: must-revalidate, post-check=0, pre-check=0, public" );
header("Expires: 0" );
readfile($filepath. $filename );
   }
?>

Re: Sécurité en forçant le téléchargement de .png

par AB » 05 avr. 2011, 16:43

ça à l'air correct à première vue.

Mais bon cela te permet apparemment de télécharger n'importe quel fichier contenu dans un répertoire déterminé. Si tu n'as besoin que de certains types de fichiers (images par exemples), limites les possibilités de téléchargement à ceux là (genre tu vérifies si l'extension du fichier est une extension que tu autorise au téléchargement).
...et j'ai peur de mettre un simple $filepath = $_GET["filepath"];
c'est une bonne réaction d'avoir peur, l'inverse serait plutôt inconscient.

Mais bon tu peux faire passer ton dossier dans l'url à condition de vérifier s'il fait partie d'une liste de dossiers autorisés (comme déjà dit).

Par exemple
$dos_autorise = array('photos-arbres','photo-chats', 'photos-chiens');

if (!in_array($_GET['dossier'],$dos_autorise)) exit('dossier non autorisé pour le téléchargemnt');

Re: Sécurité en forçant le téléchargement d'images

par Doubrovski » 05 avr. 2011, 10:38

Oui, mais dans le lien la vérification à une autre fonction : afficher ou non l'icone de download (si une image .png existe dans le dossier). Elle n'est pas liée à la sécurité.
Mais ok, c'est bien ce que je pensais, c'est dangereux...

J'ai trouvé un autre script plus sécurisant qui peut m'aider à comprendre, mais qui a pour moi deux problèmes :
-Il ne fonctionne pas du internet explorer
-il ne permet pas de choisir le dossier par variable --> et j'ai peur de mettre un simple $filepath = $_GET["filepath"];

Voici ce script :
<?php

/** path du répertoir contenant les fichiers (à éditer) **/
define('DOWNLOAD_PATH', dirname(__FILE__).DIRECTORY_SEPARATOR.'photos-arbres'.DIRECTORY_SEPARATOR);

/** on récupère le nom du fichier demandé **/
if(isset($_GET['file']))
$file = $_GET['file'];
elseif(isset($_POST['file']))
$file = $_POST['file'];
else
$file = '';

/** tant qu'a faire évitons les attaques par directory transversal **/
$file = str_replace(array('../','..\\'),'',$file);

/** la variable est elle vide, le fichier existe ? **/
if(empty($file))
exit('Please select a file for download !');
elseif(!is_file(DOWNLOAD_PATH.$file))
exit('Requested file not found !');

function getMimeType($file)
{
$mimes = array(
'hqx' => 'application/mac-binhex40',
'doc' => 'application/msword',
'dot' => 'application/msword',
'bin' => 'application/octet-stream',
'lha' => 'application/octet-stream',
'lzh' => 'application/octet-stream',
'exe' => 'application/octet-stream',
'class' => 'application/octet-stream',
'so' => 'application/octet-stream',
'dll' => 'application/octet-stream',
'pdf' => 'application/pdf',
'ai' => 'application/postscript',
'eps' => 'application/postscript',
'ps' => 'application/postscript',
'smi' => 'application/smil',
'smil' => 'application/smil',
'wbxml' => 'application/vnd.wap.wbxml',
'wmlc' => 'application/vnd.wap.wmlc',
'wmlsc' => 'application/vnd.wap.wmlscriptc',
'xla' => 'application/vnd.ms-excel',
'xls' => 'application/vnd.ms-excel',
'xlt' => 'application/vnd.ms-excel',
'ppt' => 'application/vnd.ms-powerpoint',
'csh' => 'application/x-csh',
'dcr' => 'application/x-director',
'dir' => 'application/x-director',
'dxr' => 'application/x-director',
'spl' => 'application/x-futuresplash',
'gtar' => 'application/x-gtar',
'php' => 'application/x-httpd-php',
'php3' => 'application/x-httpd-php',
'php5' => 'application/x-httpd-php',
'phtml' => 'application/x-httpd-php',
'js' => 'application/x-javascript',
'sh' => 'application/x-sh',
'swf' => 'application/x-shockwave-flash',
'sit' => 'application/x-stuffit',
'tar' => 'application/x-tar',
'tcl' => 'application/x-tcl',
'xhtml' => 'application/xhtml+xml',
'xht' => 'application/xhtml+xml',
'xhtml' => 'application/xml',
'ent' => 'application/xml-external-parsed-entity',
'dtd' => 'application/xml-dtd',
'mod' => 'application/xml-dtd',
'gz' => 'application/x-gzip',
'zip' => 'application/zip',
'au' => 'audio/basic',
'snd' => 'audio/basic',
'mid' => 'audio/midi',
'midi' => 'audio/midi',
'kar' => 'audio/midi',
'mp1' => 'audio/mpeg',
'mp2' => 'audio/mpeg',
'mp3' => 'audio/mpeg',
'aif' => 'audio/x-aiff',
'aiff' => 'audio/x-aiff',
'm3u' => 'audio/x-mpegurl',
'ram' => 'audio/x-pn-realaudio',
'rm' => 'audio/x-pn-realaudio',
'rpm' => 'audio/x-pn-realaudio-plugin',
'ra' => 'audio/x-realaudio',
'wav' => 'audio/x-wav',
'bmp' => 'image/bmp',
'gif' => 'image/gif',
'jpeg' => 'image/jpeg',
'jpg' => 'image/jpeg',
'jpe' => 'image/jpeg',
'png' => 'image/png',
'tiff' => 'image/tiff',
'tif' => 'image/tif',
'wbmp' => 'image/vnd.wap.wbmp',
'pnm' => 'image/x-portable-anymap',
'pbm' => 'image/x-portable-bitmap',
'pgm' => 'image/x-portable-graymap',
'ppm' => 'image/x-portable-pixmap',
'xbm' => 'image/x-xbitmap',
'xpm' => 'image/x-xpixmap',
'ics' => 'text/calendar',
'ifb' => 'text/calendar',
'css' => 'text/css',
'html' => 'text/html',
'htm' => 'text/html',
'asc' => 'text/plain',
'txt' => 'text/plain',
'rtf' => 'text/rtf',
'sgml' => 'text/x-sgml',
'sgm' => 'text/x-sgml',
'tsv' => 'text/tab-seperated-values',
'wml' => 'text/vnd.wap.wml',
'wmls' => 'text/vnd.wap.wmlscript',
'xsl' => 'text/xml',
'mpeg' => 'video/mpeg',
'mpg' => 'video/mpeg',
'mpe' => 'video/mpeg',
'qt' => 'video/quicktime',
'mov' => 'video/quicktime',
'avi' => 'video/x-msvideo',
);

if(false === ($pos = strrpos($file,'.')))
return isset($mimes[$file]) ? $mimes[$file] : 'application/force-download';

$ext = substr($file,$pos+1);

return isset($mimes[$ext]) ? $mimes[$ext] : 'application/force-download';
}

/**** on désactive les erreurs ****/
error_reporting(0);
/**** on désactive la compression en sortie ****/
ini_set('zlib.output_compression', 0);
$now = time();

/*** Gestion du cache ***/
header('Pragma: public');
header('Last-Modified: '.gmdate("D, d M Y H:i:s").' GMT');
header('Cache-Control: must-revalidate, pre-check=0, post-check=0, max-age=0');

/**** Informations sur la réponse HTTP elle-même ****/
header('Date: '.gmdate("D, d M Y H:i:s", $now).' GMT');
header('Expires: '.gmdate("D, d M Y H:i:s", $now+1).' GMT');
header('Last-Modified: '.gmdate("D, d M Y H:i:s", $now).' GMT');

/**** Informations sur le contenu à envoyer ****/
header('Content-Tranfer-Encoding: none');
header('Content-Length: '.filesize(DOWNLOAD_PATH.$file));
header('Content-Type: '.getMimeType($file).'; name="'.$file.'"');
header('Content-Disposition: attachement; filename="'.$file.'"');

/**** pour finir lecture du fichier ****/
readfile(DOWNLOAD_PATH.$file);
exit();

?>

Re: Forcer téléchargement .png

par AB » 05 avr. 2011, 04:13

Merci.
J'ai même modifié un peu mon lien pour ne pas avoir une page de téléchargement par dossier, et donc c'est encore moins sécurisant j'imagine.
Je fais passer une autre variable dans le lien pour faire passer le nom du dossier.

Un exemple pour vérifier l'existence du fichier ? Je vais essayer.

EDIT :
Ça irait comme ça ?
<?php
$filepath = $_GET["filepath"];
$filename = $_GET["filename"];
if (file_exists($filepath. $filename ))
{
header("Content-Type: application/force-download" );
header("Content-Transfer-Encoding: image/png\n" );
header("Content-disposition: attachment; filename=$filename" );
header("Content-Length: ".filesize($filepath. $filename));
header("Pragma: no-cache" );
header("Cache-Control: must-revalidate, post-check=0, pre-check=0, public" );
header("Expires: 0" );
readfile($filepath. $filename );
}
else
{
echo = "erreur";
}
?>
Lien :
<?php
$tele = $_SERVER['SCRIPT_NAME'];
$teleco = substr("$tele", 0, -4);
$telecopo = ".$teleco/";
$imapng = "$urlphoto/$fichiersansex.png";
$ima = "$fichiersansex.png";
if( file_exists( $_SERVER{'DOCUMENT_ROOT'} . "$imapng"))  {
echo '<a href="telecharger.php?filename='.$ima.'&filepath='.$telecopo.'" title="Haute qualit&eacute; 300 dpi"><img src="hq.png" width="19" height="11" alt"" /></a>';

} 
?>
-->> Ca ne marche pas... j'arrive à télécharger mon index.php en trafiquant l'url.
Ah ben oui la vérification faut la faire juste avant le code de chargement, dans le lien ça sert à rien.
Tester si un fichier existe ne suffit pas (index.php existe comme tu as pu le constater).
Il faut vérifier que ton fichier se trouve dans une liste de fichiers autorisés et pareil pour le dossier si tu transmet le nom du dossier.

Te plante pas dans tes vérif sinon c'est une faille de sécurité majeure.

Re: Forcer téléchargement .png

par Doubrovski » 05 avr. 2011, 01:15

Merci.
J'ai même modifié un peu mon lien pour ne pas avoir une page de téléchargement par dossier, et donc c'est encore moins sécurisant j'imagine.
Je fais passer une autre variable dans le lien pour faire passer le nom du dossier.

Un exemple pour vérifier l'existence du fichier ? Je vais essayer.

EDIT :
Ça irait comme ça ?
<?php
$filepath = $_GET["filepath"];
$filename = $_GET["filename"];
if (file_exists($filepath. $filename ))
{
header("Content-Type: application/force-download" );
header("Content-Transfer-Encoding: image/png\n" );
header("Content-disposition: attachment; filename=$filename" );
header("Content-Length: ".filesize($filepath. $filename));
header("Pragma: no-cache" );
header("Cache-Control: must-revalidate, post-check=0, pre-check=0, public" );
header("Expires: 0" );
readfile($filepath. $filename );
}
else
{
echo = "erreur";
}
?>
Lien :
<?php
$tele = $_SERVER['SCRIPT_NAME'];
$teleco = substr("$tele", 0, -4);
$telecopo = ".$teleco/";
$imapng = "$urlphoto/$fichiersansex.png";
$ima = "$fichiersansex.png";
if( file_exists( $_SERVER{'DOCUMENT_ROOT'} . "$imapng"))  {
echo '<a href="telecharger.php?filename='.$ima.'&filepath='.$telecopo.'" title="Haute qualit&eacute; 300 dpi"><img src="hq.png" width="19" height="11" alt"" /></a>';

} 
?>
-->> Ca ne marche pas... j'arrive à télécharger mon index.php en trafiquant l'url.

Re: Forcer téléchargement .png

par xTG » 04 avr. 2011, 18:08

Ton premier code est non sécurisant car tu ne vérifies pas l'existence du fichier passé en paramètre.
Il faut vérifier qu'il peut être télécharger (dans un espace web accessible et autorisé).

Re: Forcer téléchargement .png

par Doubrovski » 04 avr. 2011, 16:16

J'ai édité mon message, car j'ai trouvé une solution (j'avais oublié d'ajouter un point devant l'adresse du dossier comme ./dossier/)
Je me demande toujours si ce code ne représente pas une faille de sécurité pour mon site ?

Sécurité en forçant le téléchargement de .png

par Doubrovski » 04 avr. 2011, 13:48

Bonjour,
J'ai cherché pas mal de temps comment forcer le téléchargement d'un fichier .png
J'ai trouvé finalement, mais je me demande si ce code est sécuritaire ?

Ma page telecharger.php :
<?php
$filepath = "./dossier/";
$filename = $_GET["filename"];
header("Content-Type: application/force-download" );
header("Content-Transfer-Encoding: image/png\n" );
header("Content-disposition: attachment; filename=$filename" );
header("Content-Length: ".filesize($filepath. $filename));
header("Pragma: no-cache" );
header("Cache-Control: must-revalidate, post-check=0, pre-check=0, public" );
header("Expires: 0" );
readfile($filepath. $filename );
?>
Mon lien :
<?php
$imapng = "$urlphoto/$fichiersansex.png";
$ima = "$fichiersansex.png";
if( file_exists( $_SERVER{'DOCUMENT_ROOT'} . "$imapng"))  {
echo '<a href="telecharger.php?filename='.$ima.'" title="Haute qualit&eacute; 300 dpi"><img src="hq.png" width="19" height="11" alt"" /></a>';

} 
?>
Merci !