IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage PHP Discussion :

Se protéger du ../ dans un script de téléchargement


Sujet :

Langage PHP

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Homme Profil pro
    Employé magasin
    Inscrit en
    Août 2012
    Messages
    197
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Employé magasin

    Informations forums :
    Inscription : Août 2012
    Messages : 197
    Par défaut Se protéger du ../ dans un script de téléchargement
    Bonjour,
    j'ai une petite question assez bête.

    Je veux donner accès a des fichiers, alors j'ai mis un script qui permet de télécharger les fichiers.
    Le script a comme clé dans l'url une chaine encodée en base64 qui contient un json avec le nom du fichier et un timestamp pour donner une durée max d'accès.
    J'ai trafiqué la chaine encodée pour rajouter des caractères a des endroits aléatoires pour compliquer la vie d'une personne qui pourrait savoir décoder et j'encode a nouveau pour pas qu'on voit au premier abord mon bidouillage même si il passe inaperçu.
    Ce qui fait que si on ne sait pas comment c'est trafiqué je suppose que c'est presque impossible a décoder.

    La question que je me pose: comme c'est un script php basique trouvé sur le net, si quelqu'un arrive par hasard a trafiqué le lien et met des ../ est ce qu'il pourrait remonter dans les dossiers ? Comment je me protège est-ce que je dois manuellement vérifier si on essaye de sortir du dossier ou il y a une fonction qui sécurise cela ? Je me disais que j'aurais pu virer dans le path les ../ tout simplement et que ça pourrait suffire. Je me disais aussi que je pourrais aussi stocker les liens créés et autorisés si le lien a vraiment été créer par une personne qui a accès au serveur.
    Merci pour votre aide.

    Le code que j'ai trouvé sur le net:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    $size = filesize($path_file);
    header("Content-Type: application/force-download; name=\"" . basename($file) . "\"");
    header("Content-Transfer-Encoding: binary");
    header("Content-Length: $size");
    header("Content-Disposition: attachment; filename=\"" . basename($file) . "\"");
    header("Expires: 0");
    header("Cache-Control: no-cache, must-revalidate");
    header("Pragma: no-cache");
    readfile($path_file);
    exit();

  2. #2
    Membre Expert Avatar de darkstar123456
    Homme Profil pro
    Développeur Web
    Inscrit en
    Mars 2008
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Mars 2008
    Messages : 1 895
    Par défaut
    Bonjour,

    On manque un peu d'information pour répondre précisément à cette question
    On ne connait pas l'URL appelée et on ne voit pas d'où vient la variable $path_file.

    Néanmoins, si on considère que le script prend en paramètre la variable file (donc une URL qui ressemble à download.php?file=mon-fichier.zip par exemple)
    Il suffirait de vérifier que le fichier existe, et seulement si c'est le cas, on force le téléchargement.

    Code php : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    <?php
    // dirname(__FILE__) retourne le dossier en cours, là où se trouve ce code php
    // on définit donc dans quel dossier les fichiers qu'on peut télécharger se trouve
    // Il s'agit donc d'un sous-dossier "files" du dossier actuel
    $base_path = dirname(__FILE__) . '/files/';
    $file = $_GET['file']; // Je défini cette variable pcq elle est utilisée plus loin dans le force download mais je ne sais pas d'où elle vient en réalité ^^
    $path_file = $base_path . $file; // Pareil je ne sais pas d'où sort cette variable ^^
    // On s'assure que 
    // 1. le paramètre passé dans l'URL existe et n'est pas vide
    // 2. qu'il ne commence pas par un point
    // 3. que le fichier existe sur le serveur
    if (!empty($_GET['file']) && !preg_match('#^.#', $_GET['file']) && file_exists($path_file)) {
        // Ici on peut remettre le code pour forcer le téléchargement
        $size = filesize($path_file);
        header("Content-Type: application/force-download; name=\"" . basename($file) . "\"");
        header("Content-Transfer-Encoding: binary");
        header("Content-Length: $size");
        header("Content-Disposition: attachment; filename=\"" . basename($file) . "\"");
        header("Expires: 0");
        header("Cache-Control: no-cache, must-revalidate");
        header("Pragma: no-cache");
        readfile($path_file);
    }
    exit;

  3. #3
    Membre Expert
    Avatar de cavo789
    Homme Profil pro
    Développeur Web
    Inscrit en
    Mai 2004
    Messages
    1 797
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Mai 2004
    Messages : 1 797
    Par défaut
    Bonjour

    J'aurais aussi tendance à ajouter que basename() comme indiqué dans votre code source va faire fi de l'arborescence. Si on joue avec ./../../../secrets.php p.ex., basename() va retourner secrets.php et là, donc, on est forcément dans le dossier où vous autoriser le téléchargement.

    Ensuite vérifier la présence du fichier est en effet une excellente chose. Le mieux étant de définir un dossier comme par exemple "downloads" et y mettre vos fichiers autorisés à être télécharger. Cela donnerait donc
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    "downloads/".basename($file)
    pour garantir que le fichier se trouve dans ce dossier là et pas un autre.

  4. #4
    Expert confirmé
    Avatar de mathieu
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    10 672
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 10 672
    Par défaut
    une autre technique serait de lire la liste des fichiers dans le répertoire autorisé et ensuite vérifier que le fichier demandé est bien dans cette liste.

  5. #5
    Membre Expert Avatar de darkstar123456
    Homme Profil pro
    Développeur Web
    Inscrit en
    Mars 2008
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Mars 2008
    Messages : 1 895
    Par défaut
    @mathieu Effectivement, bonne alternative !

    Cependant, si on ne connait pas la limite possible du nombre de fichiers disponibles c'est à éviter car plus couteux en ressources

  6. #6
    Membre confirmé
    Homme Profil pro
    Employé magasin
    Inscrit en
    Août 2012
    Messages
    197
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Employé magasin

    Informations forums :
    Inscription : Août 2012
    Messages : 197
    Par défaut
    Citation Envoyé par mathieu Voir le message
    une autre technique serait de lire la liste des fichiers dans le répertoire autorisé et ensuite vérifier que le fichier demandé est bien dans cette liste.
    Je pensais vérifier avec une bdd si un lien a bien été autorisé a être créé, car si il existe pas ça serait forcément un lien modifier, mon path c'est un truc genre /var/www/dossier/fichier et j'ai peur que si quelqu'un dans le formulaire tape ../dossier/fichier
    est ce que la personne pourrait y accéder ? C'est pour ça que je pensais éviter dans l'url de pouvoir mettre ../

  7. #7
    Membre Expert Avatar de darkstar123456
    Homme Profil pro
    Développeur Web
    Inscrit en
    Mars 2008
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Mars 2008
    Messages : 1 895
    Par défaut
    Bonjour,

    Il existe plusieurs façon de faire, comme ça a été présenté ici à vous de choisir ce qui vous convient.

    Tout ce qui compte, c'est que d'une façon ou d'une autre vous fassiez la vérification que le fichier existe que soit il se trouve dans un dossier autorisé, soit qu'il s'agisse d'un fichier autorisé (dont le chemin complet est autorisé)


    Comme l'a signalé @cavo789, utiliser basename() est une bonne solution pour faire en sorte d'être sûr de ne lire que le nom du fichier et pas tout ce qu'on aurait pu mettre avant

Discussions similaires

  1. Téléchargement de fichier dans un script PHP
    Par Mikke dans le forum Langage
    Réponses: 2
    Dernier message: 04/04/2008, 11h34
  2. Requête POST dans un script bash
    Par desperado dans le forum Linux
    Réponses: 4
    Dernier message: 11/12/2007, 22h38
  3. Problème de date dans un script
    Par silef dans le forum Linux
    Réponses: 2
    Dernier message: 16/11/2004, 18h10
  4. [Apache] Erreur dans mes scripts CGI
    Par GLDavid dans le forum Apache
    Réponses: 2
    Dernier message: 28/08/2004, 06h14
  5. Boucle for dans un script cmd
    Par nicolas.ganache dans le forum Développement
    Réponses: 4
    Dernier message: 19/07/2004, 16h07

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo