Protéger le répertoire IMG/

Voici un script permettant protéger le contenu du répertoire IMG/

Pourquoi cette contrib ?

Dans le cas d’un intranet, il peut être utile de vouloir restreindre l’accès aux pièces jointes des articles ou des rubriques uniquement aux personnes autorisées à se connecter au site. (Cf : #LOGIN_PUBLIC et #URL_LOGOUT)

Spip stocke l’ensemble des documents (publiés ou non) dans le répertoire IMG/ . N’importe qui peut consulter ces documents (images, fichiers pdf, word...) en allant à l’adresse http://www.votresite.com/IMG/ ou en connaissant l’url d’un document. Cette contrib permet donc de corriger ce problème et de restreindre l’accès à vos données.

I. Ne pas lister le contenu des répertoires

La première chose à faire est d’empêcher Apache de lister le contenu des répertoires ne contenant pas de fichier « index ». Pour cela, il faut placer un fichier nommé .htaccess à la racine de votre site. Ce fichier doit contenir les lignes suivantes :

ErrorDocument 404 erreur404.php3
options -indexes


-  La première ligne permet de rediriger l’internaute lorsque la page demandée n’existe pas. Pour cela, vous devez créer un squelette d’erreur (couples de fichier erreur404.php3/erreur404.html)
-  La deuxième ligne empêche Apache de lister le contenu des répertoires ne possédant pas de fichier « index »
-  Ces règles s’appliquent au répertoire racine et à ses sous-répertoires.

II. Protéger le répertoire IMG/

1. - Créer un fichier .htaccess à la racine du répertoire IMG/ contenant les instructions suivantes

ErrorDocument 404 ../erreur404.php3

<IfModule mod_rewrite.c>
        RewriteEngine On
        RewriteRule "\.(doc|pdf|sxw|ppt|ps|txt|xls|html|DOC|PDF|SXW|PPT|PS|TXT|XLS|HTML)$" ../securedoc.php3
</IfModule>

<IfModule !mod_rewrite.c>
        <IfModule mod_access.c>
                <Files ~ "\.(doc|pdf|sxw|ppt|ps|txt|xls|html|DOC|PDF|SXW|PPT|PS|TXT|XLS|HTML)$">
                        Deny from all
                        ErrorDocument 403 ../securedoc.php3
                </Files>
        </IfModule>
</IfModule>


-  Pour info : Afin de ne pas trop surcharger le serveur, les fichiers protégés sont uniquement les fichiers : doc, pdf, sxw, ppt, ps, xls, html et txt. Si vous voulez protéger d’autres types de fichiers, vous devez rajouter des extensions (ex : gif, jpg...).

2. - Créer le fichier securedoc.php3 à la racine de votre site.

<?php

include("ecrire/inc_version.php3");


function not_found() {
	http_status(404);
	Header("Location: erreur404.php3");
	exit;
}

$uri = $REQUEST_URI;

if ($HTTP_COOKIE_VARS['spip_session'] OR ($PHP_AUTH_USER AND !$ignore_auth_http)) {
	include_ecrire ("inc_session.php3");
	if (verifier_visiteur()){
	
		
		if (!ereg("/IMG/",$uri) || !ereg("..",$uri)){
			not_found();
		}
	
		$fichier = preg_replace(",^.*/IMG/,", "IMG/", $uri);
		if (!@file_exists($fichier) || !@is_file($fichier)){
			not_found();
		}
		
			
		$size = @filesize($fichier);
		if (!$size){
				not_found();
		}
		
		
		$if_modified_since = ereg_replace(';.*$', '', $HTTP_IF_MODIFIED_SINCE);
		$gmoddate = gmdate("D, d M Y H:i:s", @filemtime($fichier))." GMT";
		if ($if_modified_since == $gmoddate) {
			http_status(304);
			exit;
		}
		http_status(200);
		
		$nom=ereg_replace(".*/","",$fichier);
		$extension=ereg_replace("^(.*)\.(.*)$", "\\2", $nom);
		$req= "SELECT mime_type FROM spip_types_documents WHERE extension='".$extension."'";
		$res = spip_query($req);
		if (spip_num_rows($res)>0){
			$row = spip_fetch_array($res);
			$mimeType = $row['mime_type'];
			Header('Content-Type: '.$mimeType);
		}
	
		Header("Content-Length: ".$size);
		Header("Last-Modified: ".$gmoddate);	
		Header('Content-Disposition: attachment; filename="'.$nom.'"');
		
		readfile($fichier);
	}
	else {
		not_found();
	}
}
else {
	not_found();
}


?>

3. - Exécuter le script SQL suivant qui va compléter les champs mime_type de la table spip_types_documents qui par défaut sont vides.

script SQL

III. Comment çà marche ?


-  Le fichier « IMG/.htaccess » redirige les demandes de documents de l’internaute vers le fichier « securedoc.php3 »
-  Le script « securedoc.php3 » vérifie si l’internaute est connecté. Dans ce cas, le script effectue plusieurs vérifications (Est-ce que le fichier existe ; Est ce que sa taille est supérieure à 0...). Enfin, il récupère le type mime du document, complète les en-têtes http de la page et retourne le document à l’internaute.
-  Dans le cas inverse, une erreur 404 est retournée au navigateur.

IV. L’archive de la contrib

Protéger le répertoire IMG/ (Authentification)
Cette version impose à l’utilisateur d’être connecté.
Protéger le répertoire IMG/ (Referer)
Cette légère variante n’impose pas d’authentification, mais teste la présence d’un referer. Attention les navigateurs ne retournent pas toujours le referer de la page consultée. Ce qui peut poser des problèmes dans certains cas

-  Ce script est très inspiré de celui d’Antoine publié sur la liste de diffusion spip-devel.

Discussion

16 discussions

  • Ceci est-il toujours valable sous SPIP 2.0.3 ? Je me contente actuellement de mettre un fichier index.html dans tous les répertoires dont je ne souhaite pas que le contenu puisse être accédé directement par les utilisateurs. Qu’est-ce que je risque ? En quoi la méthode proposée ici est-elle plus sécurisante ?
    En tous cas merci pour cette contrib.
    Pierre

    Répondre à ce message

  • J’ai adapté cette contrib sur un spip 1.9.2d, mais je voulais en plus que ce qui est écrit plus loin dans le forum, protéger les images et les vignettes générées automatiquement.

    Pour protéger les images, il faut ajouter au .htaccess :
    gif|GIF|png|PNG|jpg|JPG|jpeg|JPEG dans les 2 ocuurences (doc|pdf|sxw|ppt|ps|txt|xls|html|DOC ... de ce fichier.

    Ensuite, pour plus de cohérence avec spip 1.9, je sugère de renomer erreur404.php3 et securedoc.php3, erreur404.php et securedoc.php, et d’adapter leurs occurences dans le .htaccess et securedoc.php

    Ensuite, comme dit plus bas, il faut dans securedoc.php remplacer :
    include("ecrire/inc_version.php3");
    par

    include("ecrire/inc_version.php");
    include("ecrire/inc/headers.php");

    Maintenant, il faut penser à protéger les vignettes qui avec spip 1.9 se trouvent désormais dans un cache dans le répertoire /local/. Pour cela, il faut :
    1) placer le .htaccess dans le répertoire /IMG/ ET /local/
    2) dans securedoc.php, remplacer

    		if (!ereg("/IMG/",$uri) || !ereg("..",$uri)){
    			not_found();
    		}
    	
    		$fichier = preg_replace(",^.*/IMG/,", "IMG/", $uri);
    		if (!@file_exists($fichier) || !@is_file($fichier)){
    			not_found();
    		}

    par

                    if ((!ereg("/IMG/",$uri) && !ereg("/local/",$uri)) || !ereg("..",$uri)){
                            not_found();
                    }
    
                    if (ereg("/IMG/",$uri)) {$fichier = preg_replace(",^.*/IMG/,", "IMG/", $uri);}
                    if (ereg("/local/",$uri)) {$fichier = preg_replace(",^.*/local/,", "local/", $uri);}
                    if (!@file_exists($fichier) || !@is_file($fichier)){
                            not_found();
                    }

    Chez moi, ça marche ...
    bien à vous.

    Répondre à ce message

  • 11

    Bonjour,

    merci pour cette contrib.
    Je viens de tester la solution.
    En l’utilisant telle quelle j’obtenais un message d’erreur « undefined » sur la fonction « http_status() ».
    Je l’ai remplacée par un « header() », dans securedoc.php3, et ça marche !

    Le seul inconvenient pour mon site est que je voudrais pouvoir garder des documents joints en accès libre, sans identification du lecteur.
    Or toutes les images et douments joints sont envoyés par SPIP dans le répertoire IMG.

    Est ce qu’on peut forcer SPIP à changer de répertoire, pour certaines rubriques par exemple ?

    • Quant à moi, j’ai fait le contraire :
      J’ai ajouté

      include(« ecrire/inc/headers.php ») ;

      au début du fichier securedoc.php3.

      Salutations ;-)

    • Bonjour,

      j’esaie d’utiliser cette astuce pour protéger l’accès au fichier dans IMG s’il n’y a pas de session ouverte.

      J’utilise le plug-in accès restreint pour gérer mes accès utilisateurs.

      j’ai modifié la ligne include(« ecrire/inc_session.php3 ») par include(« ecrire/inc/session.php ») car je travaille sur la version 1.9.2.

      J’ai un message d’erreur 403 forbidden lorsque j’essaie d’accède raux documents soit par accès direct soit par le lien proposé par l’article sur SPIP.

      Y’a t’il d’autre choses à modifier ?

    • Bonjour,

      Pour ma part, j’ai uniquement interdit l’accès direct aux fichiers du répertoire IMG (et à ses sous-rep) et je gère un accès restreint sans plugin en autorisant uniquement l’accès au(x) auteur(s) des articles dont je veux limiter l’accès.

      As-tu essayé de rajouter la ligne :

      include(« ecrire/inc/headers.php ») ;

      au début de securedoc.php ?

      Salutations

    • Oui je l’ai rajouté.

      L’accès à mes docs est verrouillé aussi bien en ayant ouvert une session qu’en copiant collant le lien vers le dans le champ adresse de firefox.

      tu as seulement rajouter cette ligne de code sans autres modifs ?

    • Voici le contenu de mon fichier securedoc.php3 :

      <?php
      
      include("ecrire/inc_version.php");
      include("ecrire/inc/headers.php");
      
      function not_found() {
          http_status(404);
          exit;
      }
      
      $uri = $REQUEST_URI;
      $referer=$HTTP_REFERER;
      
      if (ereg(lire_meta("adresse_site"),$referer)){
          
          if (!ereg("/IMG/",$uri) || !ereg("..",$uri)){
              not_found();
          }
      
          $fichier = preg_replace(",^.*/IMG/,", "IMG/", $uri);
          if (!@file_exists($fichier) || !@is_file($fichier)){
              not_found();
          }
          
              
          $size = @filesize($fichier);
          if (!$size){
                  not_found();
          }
          
          
          $if_modified_since = ereg_replace(';.*$', '', $HTTP_IF_MODIFIED_SINCE);
          $gmoddate = gmdate("D, d M Y H:i:s", @filemtime($fichier))." GMT";
          if ($if_modified_since == $gmoddate) {
              http_status(304);
              exit;
          }
          http_status(200);
          
          $nom=ereg_replace(".*/","",$fichier);
          $extension=ereg_replace("^(.*)\.(.*)$", "\\2", $nom);
          $req= "SELECT mime_type FROM spip_types_documents WHERE extension='".$extension."'";
          $res = spip_query($req);
          if (spip_num_rows($res)>0){
              $row = spip_fetch_array($res);
              $mimeType = $row['mime_type'];
              Header('Content-Type: '.$mimeType);
          }
      
          Header("Content-Length: ".$size);
          Header("Last-Modified: ".$gmoddate);    
          Header('Content-Disposition: attachment; filename="'.$nom.'"');
          
          readfile($fichier);
      }
      else {
          not_found();
      }
      
      
      ?>

      et celui du fichier .htaccess situé dans le répertoire IMG :

      ErrorDocument 404 http://127.0.0.1/intranet/erreur404.php3

      <IfModule>
      RewriteEngine On
      RewriteRule « \.(doc|pdf|sxw|ppt|ps|txt)$ » ../securedoc.php3


      <IfModule>

      Deny from all
      ErrorDocument 403 ../securedoc.php3


      J’ai eu la flemme de créer une page d’erreur à la place de « http://127.0.0.1/intranet/erreur404.php3 ».

      Et puis c’est tout...

      Comme tu le vois : c’est le minimum syndical et cela marche.

      Par contre, je n’ai pas modifié le fichier .htaccess situé dans le répertoire principal du site avec les options

      ErrorDocument 404 erreur404.php3
      options -indexes

      comme indiqué au début...

      Mais je ne sais plus pourquoi je ne l’ai pas fait, ça remonte à 6 mois...

      En tout cas, ça marche comme je le voulais.

    • Dans

      if (ereg(lire_meta(« adresse_site »),$referer))

      dis moi si je me trompe mais le « adresse_site » correspond à par exempel http://127.0.0.1/intranet?

    • Ok ça à l’air de fonctionner, j’ai repris la première version du code et en mixant en rajoutant quelques ajustement avec le tien et j’obtiens ce que je souhaitais !
      Reste plus qu’à créer les pages d’erreur !

      merci pour ton aide !

    • Pour info, sur le document securedoc.ph je pense faire des petits réajustement en fonction du plug in accès restreint, car à l’heure actuel le prog vérifie juste qu’une session est ouverte mais pas par qui ce qui peut poser problème suivant le profil du connecté

    • Quant à moi, je ne préoccupe pas de savoir si le visiteur est loggué ou non à ce stade là.

      C’est dans le squelette de la page que je vérifie si le visiteur l’est et s’il fait parti des auteurs de la page...

      Donc, c’est + simple pour moi...

      Quant à ma page erreur404, il faut d’abord que je me sorte les doigts du c## pour en faire une + claire...

      @ +

    • suite à un changement de serveur la protection de mes docs est remise en cause alors que était Ok (impossiblité d’ouvrir les docs si non connecté).
      C’est dur de se remettre dans le code, je fais donc appel à des personnes qui comme moi ont subi ce type de désagréments pour avoir des pistes sur les éventuels changement à opérer.

    • réponse à moi-même :
      il semble qu’après test que le problème vienne du .htaccess du dossier IMG/.
      J’ai fait intervenir mon administrateur serveur pour qu’il me file un coup de main mais pour le moment pas de réponse...mais ça fait 24h et je n’ai pas de retour il doit sécher aussi sur le problème...

    Répondre à ce message

  • Le script à l’air de bien fonctionner, mais quelqu’un pourrait me dire comment faire pour la 1.9.2d car l’article est assez vieux (2004)...

    Merci beaucoup !

    Répondre à ce message

  • 2

    Bravo pour ce script que je n’ai pas essayé !!! Je place simplement un fichier index.html qui ne contient rien à la racine du dossier IMG et de ces sous-dossiers. Je suis conscient que la protection est « jeune », mais elle fait son effet...

    Répondre à ce message

  • Excellente Contrib !! Merci Aurélien.

    Juste une précision sur le fichier .htaccess quand l’Apache tourne sur un OS Windows :
    La première ligne doit juste être :
    ErrorDocument 404 /erreur404.php3

    sans les ../

    Sinon le fichier .htaccess renvoit sur une page vide indiquant ../erreur404.php3

    Répondre à ce message

Ajouter un commentaire

Avant de faire part d’un problème sur un plugin X, merci de lire ce qui suit :

  • Désactiver tous les plugins que vous ne voulez pas tester afin de vous assurer que le bug vient bien du plugin X. Cela vous évitera d’écrire sur le forum d’une contribution qui n’est finalement pas en cause.
  • Cherchez et notez les numéros de version de tout ce qui est en place au moment du test :
    • version de SPIP, en bas de la partie privée
    • version du plugin testé et des éventuels plugins nécessités
    • version de PHP (exec=info en partie privée)
    • version de MySQL / SQLite
  • Si votre problème concerne la partie publique de votre site, donnez une URL où le bug est visible, pour que les gens puissent voir par eux-mêmes.
  • En cas de page blanche, merci d’activer l’affichage des erreurs, et d’indiquer ensuite l’erreur qui apparaît.

Merci d’avance pour les personnes qui vous aideront !

Par ailleurs, n’oubliez pas que les contributeurs et contributrices ont une vie en dehors de SPIP.

Qui êtes-vous ?
[Se connecter]

Pour afficher votre trombine avec votre message, enregistrez-la d’abord sur gravatar.com (gratuit et indolore) et n’oubliez pas d’indiquer votre adresse e-mail ici.

Ajoutez votre commentaire ici

Ce champ accepte les raccourcis SPIP {{gras}} {italique} -*liste [texte->url] <quote> <code> et le code HTML <q> <del> <ins>. Pour créer des paragraphes, laissez simplement des lignes vides.

Ajouter un document

Suivre les commentaires : RSS 2.0 | Atom