2010-08-12 27 views
8

J'utilise un plan d'hébergement Web GoDaddy sur une plate-forme Windows. Ce n'était pas mon choix - il doit faire avec une partie différente du site réel en utilisant ASP.NET (aussi pas mon choix).Restreindre l'accès aux fichiers - uniquement lire via PHP

J'ai une base de données SQL avec un tas d'entrées avec des informations client non sensibles. La clé primaire sur ceci est un entier AutoIncrement, et j'ai une série de fichiers PDF qui correspondent à chacun de ces entiers (par exemple 555.pdf, 7891.pdf, etc.).

Mon but est de limiter l'accès direct à ces fichiers, je veux que les utilisateurs doivent d'abord passer par un processus de recherche et de connexion (PHP). A l'origine j'avais prévu de placer les fichiers au dessus du dossier PUBLIC_HTML, mais GoDaddy refuse de me donner un accès root sans un serveur dédié (20 $ par mois d'eux).

La prochaine chose que j'ai regardée était HTACCESS. J'allais restreindre l'accès aux fichiers aux seuls scripts PHP en autorisant uniquement l'accès à l'adresse IP du serveur (ou localhost/127.0.0.1). Malheureusement, cela ne fonctionne pas car GoDaddy n'exécute pas Apache sur ses serveurs Windows.

Je pourrais mettre les fichiers dans les BLOB dans la base de données, mais cela devient vraiment compliqué quand j'ai besoin de travailler rapidement avec eux (en plus j'ai eu quelques problèmes avec cette approche).

Des suggestions pour limiter l'accès aux fichiers uniquement à un script PHP (readfile())?

+0

Cela dépend du serveur Web qu'ils utilisent (IIS, supposons). Peut-être que vous devriez marquer cela avec IIS. – Artefacto

Répondre

5

Puisque vous ne pouvez pas mettre les fichiers partout, mais dans votre répertoire public_html, vous devrez aller pour la peur/haï méthode « sécurité par l'obscurité »

  1. Créer un sous-répertoire nommé de façon aléatoire pour stocker les fichiers dans: public_html/RANDOMGARBAGE

  2. Assurez-vous que le répertoire ne peut pas être parcouru. Désactivez la navigation dans les répertoires (si vous le pouvez), et mettez un document par défaut (index.html?) Là aussi, donc même si la navigation est activée, vous n'obtiendrez pas la liste du répertoire. Ne stockez pas vos fichiers avec des noms devinables. Au lieu de les stocker avec l'ID de la base de données, stockez-les avec un nom + haché salé à la place: $crypted_filename = sha1($real_filename . 'some hard-to-guess salt text'); (bien sûr, rendre ceci plus complexe si vous en avez besoin). Stockez le nom de fichier d'origine dans votre base de données. Donc, vous vous retrouvez avec quelque chose comme:

    public_html/RANDOMGARBAGE/5bf1fd927dfb8679496a2e6cf00cbe50c1c87145 public_html/RANDOMGARBAGE/7ec1f0eb9119d48eb6a3176ca47380c6496304c8

  3. Servez les fichiers via un script PHP - jamais un lien vers le fichier haché directement

    Télécharger

qui a ensuite fait:

<?php 

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

    $crypted_file = sha1($fileID . 'some hard-to-guess salt text'); 

    $full_path = 'public_html/RANDOMGARBAGE/' . $crypted_file; 
    if (is_readable($full_path)) { 
     if(user_is_allowed_to_see_this_file()) { 
      /// send file to user with readfile() 
      header("Content-disposition: attachment; filename=$ORIGINAL_FILENAME"); 
      readfile($full_path); 
     } else { 
      die("Permission denied"); 
     } 
    } else { 
     /// handle problems here 
     die("Uh-oh. Can't find/read file"); 
    } 

De cette façon, l'utilisateur ne verra jamais ce que votre nom « s00per seekrit » est, ils vont simplement voir leur navigateur a frappé ...php?fileID=37 et lancer un téléchargement de secret file.pdf

En plus de cela, vous pouvez parfois renommer le sous-spéciale répertoire à quelque chose d'autre sur une base régulière, ainsi que de modifier le texte de sel (qui nécessite alors que vous mettez à jour tous les noms de fichiers hachés avec les nouvelles valeurs sha1).

0

Vous pouvez simplement les masquer. C'est la sécurité par l'obscurité, mais cela semble être votre meilleure option si vous ne pouvez pas les garder hors de la racine web, ou trouver un moyen de dire au serveur de ne pas les servir directement.

les coller Ainsi, dans un répertoire au hasard nommé:

asd8b8asd8327bh/123.pdf 
asd8b8asd8327bh/124.pdf 
asd8b8asd8327bh/125.pdf 
... 

Puis vous écrire un petit script PHP qui envoie les en-têtes appropriés, et de transmettre le contenu du fichier par le biais.

par exemple:

<?PHP 
//pdf.php 
$id = $_GET['id']; 

//make sure nobody is doing anything sneaky. is_numeric() might do the trick if the IDs are always integers. 
if (!some_validation_passes($id)){ 
    die(); 
} 
<?php 

header('Content-type: application/pdf'); 
header('Content-Disposition: attachment; filename="'.$id.'.pdf"'); 
readfile('asd8b8asd8327bh'.$id.'pdf'); 

Maintenant, ce qui précède est vraiment pas mieux que de servir les fichiers directement (encore), puisque les gens peuvent encore augmenter le paramètre id dans la chaîne de requête.

Mais vous devriez être capable de comprendre comment gérer l'autorisation assez facilement.

+0

Ceci est la sécurité à travers l'obscurité. En d'autres termes, pas sécurisé. – Borealid

+0

@Borealid Vous dites cela comme si je n'avais pas explicitement qualifié ma réponse dans la première ligne. Ne pas entrer dans un débat sur la sécurité à travers l'obscurité mais "C'est un logiciel, autrement dit, pas sécurisé". Ou "Ceci est un système de mot de passe, et donc peu sûr". En fait, maintenant que j'y pense, ma solution est à peu près aussi sûre qu'un mot de passe fort, en supposant qu'aucun trou indépendant ne permette à un attaquant de lister les répertoires. – timdev

0

Rendre un dossier Web inaccessible via chmod. PHP sera toujours capable d'inclure/exiger ce qui est sur le serveur, mais les utilisateurs ne pourront pas accéder aux fichiers.

Exemple: Ceci est défini sur 770, l'utilisateur et le groupe IE peuvent lire/écrire/exécuter, l'autre ne peut rien faire.

+0

Cette réponse est fausse. À l'exception d'une configuration SuExec/CGI, PHP utilise les autorisations du serveur Web. Si le fichier est inaccessible au serveur web, il est également inaccessible à PHP. – Borealid

+0

J'ai un dossier défini à 770 et je suis en mesure d'inclure, mais je suis incapable de naviguer directement dans mon navigateur. – Robert

+0

Aussi je pense que vous avez mal compris, le serveur Web a toujours des autorisations, l'utilisateur et le groupe ont des autorisations dans 770, d'autres ne le font pas. Donc, cela donne à PHP un accès complet aux fichiers, le navigateur Web n'obtiendra rien. – Robert

1

Parce que PHP utilise les autorisations de l'utilisateur du serveur web, il n'y a aucun moyen de restreindre l'accès aux fichiers sans soit:

  • En les plaçant en dehors de la docroot
  • Modification de la configuration du serveur Web pour interdire l'accès à ceux fichiers
  • Modification du fichier de sorte qu'il sera interprété par le serveur Web, cachant ainsi son contenu

les mettre dans un compte de base de données outsi du DOCROOT. Pour la troisième option, vous pourriez faire les fichiers PHP de fichiers PDF, mais honnêtement, ce serait assez compliqué.

Je vous recommande de contacter GoDaddy et de voir s'ils ont un moyen de configurer les autorisations de fichiers par répertoire.

+0

Clever. En supposant que OP ne puisse rien faire pour le serveur, j'aime votre troisième option, couplée avec le code de base que j'ai décrit. – timdev