La securisation d'un site web.

L'un des aspects essentiels d'un site web est tres souvent négligé : la sécurité. C'est pourtant courir le risque de perdre l'intégralite de ses fichiers du jour au lendemain, de voir le contenu de son site vandalisé ou de transmettre des données confidentielles à des tiers. Plus communément, votre site peut etre rendu totalement inaccessible, independamment de la volonte de votre hebergeur. D'où proviennent les failles?

Le niveau de sécurité d'un service dépend de nombreux facteurs :infrastructure physique, équipement réseau, architecture du réseau, moyens de sauvegarde, redondance, supervision, systèmes d'exploitation, logiciels employés, configuration, droits d'accès, scripts... Autant de points qui méritent chacun la plus grande attention, car la moindre brisure dans cette chaîne est en mesure de provoquer son ébranlement.

Les premiers éléments sont bien entendu laissés aux bons soins de votre hébergeur, vous devez juste vous assurer que les mesures minimales ont bien été prises. En revanche, tout le contenu des sites webs est sous l'entière responsabilité de leur propriétaire.

La protection du contenu par authentification.

Certaines pages de votre site web ne doivent peut-etre pas etre librement consultables. Cela inclut par exemple les scripts d'administration et les zones membres. A cet effet, les serveurs web ont la faculté de pouvoir protéger des répertoires par mot de passe. Les pages s'y trouvant sont alors inaccessiblessi le client ne fournit pas de preuve d'authentification. Cette preuve est consitutuée de trois éléments : - Un nom de "zone", caractéristique d'un ensemble de pages. Un utilisateur authentifié auprès d'une zone est en mesure de consulter toutes les pages se trouvant dans la meme zone sans entrer de nouveau les données d'authentification. - Un nom d'utilisateur. - Un mot de passe.

Les serveurs proposent souvent de nombreuses méthodes pour stocker lesinformations nécessaires à l'authentification, les plus courantes étant les annuaires LDAP, les bases SQL, et les serveurs Radius. Ces méthodes sont en effet indispensables aux hébergeurs pour centraliser les comptes clientset les exploiter via différents services : web, ftp, dns, mail, facturation... Cependant, l'accès à un annuaire LDAP ou à l'authentification via un serveurSQL est rarement proposé sur des serveurs d'hébergement mutualisé.

Tout espoir n'est pas perdu puisqu'il est généralement possible de stocker les données nécessaires à l'authentification web dans de simples fichiers texte. Inutile d'espérer y enregistrer des millions de comptes en conservant des performances correctes, mais lorsqu'il s'agit simplement deréserver certaines zones à quelques utilisateurs prédéfinis, cette méthode s'avère très largement suffisante. La protection de zones par mot de passe peut s'effectuer exactement de la meme manière sous Zeus, Caudium, Roxen et Apache. Il y a donc fort à parierque ce que nous allons décrire ici fonctionne sans soucis chez la plupart deshébergeurs et serveurs dédiés. Bien qu'il soit tout à fait envisageable de protéger individuellement des fichiers explicitement listés, il est généralement plus commode de travailler sur des répertoires entiers.

La convention employée par les serveurs web précédemment cités consiste à vérifier la présence d'un fichier nommé '.htaccess' dans tous les répertoires menant à une page destinée à etre envoyée. Le cas échéant, le contenu du fichier est analysé de façon à modifier temporairement la configuration du serveur web avant d'envoyer la page concernée.

Il est important de bien comprendre que chaque répertoire menant au fichier contenant la page est lu, de façon à prendre en considération tous les fichiers '.htaccess' éventuels.

Prenons l'exemple d'une vidéo située dans /www/html/videos/free/42.mpeg ., avec des fichiers '.htaccess' comme suit : - /www/.htaccess : le fichier contient des directives qui indiquent au serveurque *toutes* les pages sont interdites. On peut donc placer des fichiers privés dans ce répertoire (bases de données, essais divers, bibliothèques...) .

- /www/html/.htaccess : le fichier indique que toutes les pages dont l'extension est '.html' ou '.php' sont autorisées. Tous les autres fichiers dépendent du fichier .htaccess du repertoire précédent, et sont donc interdits. En autorisant explicitement certaines extensions, on évite l'accès aux fichiers laissés par inadvertance dans ce repertoire, aux copies de sauvegardes, etc.

- /www/html/videos/.htaccess : le fichier n'autorise l'envoi qu'après authentification (zone membre) .

- /www/html/videos/free/.htaccess : le fichier autorise l'envoi sans authentification de tous les fichiers dont l'extension est '.mpeg' ou '.mpg'.

Les droits d'accès au fichier 42.mpeg sont déterminés d'après l'ensemble des fichiers .htaccess qui y mènent, évalués dans l'ordre. Un fichier'.htaccess' situé dans un sous-repertoire peut comporter des directives qui annulent totalement celles déclarées dans le répertoire parent. C'est ici le cas : /www/html/videos/ nécessite une authentification, mais /www/html/videos/free/ s'en dispense (zone "visiteurs" avec des exemples). En l'absence d'un fichier '.htaccess', on hérite des propriétés du répertoire parent, ou, à défaut, de la configuration d'origine du serveur web. Si l'on retire le fichier /www/html/videos/free/.htaccess, les fichiers contenus dans ce répertoire deviennent uniquement accessibles après authentification. Il est temps de s'attarder sur le contenu proprement dit de ces fameux fichiers '.htaccess' . Celui-ci peut etre très complexe et composé d'un assemblage de nombreuses directives. Nous allons ici nous restreindre à ceux de l'exemple ci-dessus, qui sont sans doutes les plus courants.

Comment interdire l'accès à un répertoire.

Voici le contenu d'un fichier '.htaccess' empechant la lecture de tout ce qui se trouve dans le répertoire courant (et de ses sous-repértoires, faute de règle inverse dans d'autres fichiers '.htaccess') : Order deny,allowDeny from allSatisfy all Ces lignes devraient constituer les règles par défaut de tout site web correctement configuré : tout est interdit, et l'on autorise ensuite explicitement le contenu.

Comment autoriser certains fichiers.

Un exemple étant souvent plus parlant qu'une myriade de détails techniques, voici comment autoriser tous les fichiers '.avi':

<Files ~ "\.avi$">
Order allow,deny
Allow from all
Satisfy all
</Files>

Etendons cet exemple aux fichiers '.avi', '.mpg' et '.mpeg' :

<Files ~ "\.(avi|mpg|mpeg)$">
Order allow,deny
Allow from all
Satisfy all
</Files>

Notez que le '.' composant un nom de fichier doit obligatoirement etre précédé d'un backslash (faute de quoi il fait office de joker et non de caractère défini) . De meme, la fin du nom du fichier est symbolisée par le symbole '$' . Si celui-ci doit figurer dans le nom d'un fichier, il faut là aussi le faire précéder d'un backslash. Le caractère '|' sépare les différentes propositions d'une liste, ici délimitée par des parenthèses.


Comment restreindre l'accès aux utilisateurs authentifiés.

Les choses vont maintenant se compliquer légèrement. Nous avons vu qu'un ensemble de pages protégées faisait intervenir deux facteurs : - Un nom de zone : toutes les pages faisant partie de la meme zone fonctionneront avec les memes données d'authentification. Concrètement, le client ne verra la boite de dialogue d'authentification s'afficher qu'une fois par zone et par session.

- Un couple nom d'utilisateur/mot de passe. Par commodité, l'ensemble de ces couples va etre placé dans un fichier distinct du fichier '.htaccess'.

<Files ~ "^\.ht">
Order deny,allow
Deny from all
Satisfy all
</Files>

AuthType BasicAuthName
"Zone membre"
AuthUserFile "www/html/videos/.htpasswd"
Require valid-user
Satisfy all


Le premier groupe de directives (<Files>...</Files>) interdit l'accès à tous les fichiers dont le nom débute par '.ht' . En l'occurrence, ce sont'.htaccess' et '.htpasswd' qui sont visés, afin d'éviter qu'un visiteur ne puisse consulter la liste des comptes existants. Ces règles font souvent partie des règles par défaut du serveur web, mais les ajouter explicitement dans un fichier .htaccess évite toute mauvaise surprise.

Nous indiquons ensuite au serveur que l'accès aux fichiers nécessite d'etre authentifié, n'importe quel utilisateur étant accepté ("Require valid-user"). La zone se nomme "Zone membre" et le fichier contenant les paires nomd'utilisateur/mot de passe se nomme ".htpasswd" (nom souvent choisi par convention) . Le chemin www/html/videos/.htpasswd" est relatif à la racine des fichiers composant les pages web. Dans quasiment tous les cas, il s'agit simplement du répertoire où se trouve le fichier, tel qu'il est visible dans un client FTP. Attention à ne pas précéder le chemin d'un slash pour que cela soit vrai : 'www/html/videos/.htpasswd' correspond bien à cette définition, tandis que '/www/html/videos/.htpasswd' est un chemin absolu, qui nécessite des informations à obtenir auprès de votre hébergeur (pour un résultat identique) .

"AuthType Basic" indique le protocole d'authentification àadopter : le plus simple et le moins sécurité (tous les mots de passe circulent en clair) . Ce n'est malheureusement pas un choix délibéré mais parce que c'est le seul protocole compatible avec la majorité des brouteurs.Pour d'avantage de sécurité, une zone protégée doit etre placée sur unserveur sécurisé (HTTPS), si votre hébergeur en dispose.

La directive "Satisfy" prend toute son importance lorsque plusieurs critères déterminent l'accès à un fichier. Elle permet en effet de choisir si un seul critère ("any") est déterminant, ou si tous doivent etre passés en revue("all").

Ici nous avons deux principaux critères pour que l'accès à un fichier soit autorisé ou refusé : - L'extension du fichier, héritage directe du fichier .htaccess du répertoire précédent, dans notre exemple.

- L'authentification du client.

Avec "Satisfy any", le fait d'etre authentifié suffit à accéder à un fichier. Par conséquent, il serait possible de consulter 'abc.doc' bien qu'interdit par les fichiers .htaccess des répertoires précédent. Nous utilisons donc systématiquement 'Satisfy all' pour bénéficier d'une sécurité maximale. Dès l'instant où le fichier .htpasswd est en place, toute tentative d'accès au répertoire se solde immédiatement par l'apparition d'une boite d'authentification. Encore faut-il créer la liste des utilisateurs valides pour que l'authentification dispose d'un réel intéret.


La création des listes d'utilisateurs.

Les paires nom d'utilisateur/mot de passe sont placées dans le fichier.htpasswd sous une forme très basique puisqu'il s'agit d'une suite de ligne de la forme :

nom d'utilisateur:mot de passe hashé

Le mot de passe n'est pas stocké en clair, mais sous la forme d'un nombre, résultant d'une fonction à sens unique appliquée aux caractères qui composent le code. Les fonctions les plus courantes sont :

- Le DES. C'est une fonction historique, à éviter de nos jours. D'une partelle est très rapide à décrypter, en essayant toutes les possibilités à l'aide des nombreux outils destinés à cet effet. Ensuite, elle limite la taille des mots de passe à 8 caractères, ce qui diminue encore son intéret.Encore plus genant : cette fonction n'existe pas sur tous les systèmes. Elle a été définitivement abandonnée par certaines variantes d 'Unix et aucun serveur sous Windows ne l'implémente. C'est pourquoi le serveur Apache la déconseille depuis 4 ans (date de la sortie de la version 1.3, avec de nouvelles fonctions pour remplacer le DES) . En utilisant le DES, vos fichiers .htpasswd peuvent s'arreter de fonctionner du jour au lendemain, si l'hébergeur effectue une mise à jour logicielle.

- Le MD5. Cette fonction est bien plus sure que la précédente et elle est reconnue par un grand nombre de logiciels. Néanmoins, elle est employé différemment selon les serveurs. Ainsi, Apache y ajoute une graine qui la rend incompatible avec d'autres logiciels qui se basent pourtant sur la meme fonction. - Le SHA1. Cette fonction, bien qu'inventée par la NSA, est considérée comme la plus sure à l'heure actuelle. Elle a l'avantage d'etre universelle car totalement compatible avec la plupart des serveurs web, FTP, LDAP, mail... Voici à quoi ressemble le couple nom d'utilisateur/mot de passe hashé d'un fichier .htpasswd avec ces trois cryptages :

DES (56 bits) : toto:Z61EVRs6PJ34Q
MD5 (128 bits) : toto:$apr1$fEIqI/..$tFh.ivIKnp0paKX0yrP5a0
SHA1 (160 bits): toto:{SHA}C5wmJdwh7wX2rU3fR8XyA4N6oyw=

Pour appliquer la fonction SHA1 à un mot de passe et obtenir un résultat pret à etre inséré dans un fichier .htpasswd, on peut utiliser le moduleDigest::SHA1 de Perl (méthode b64digest) . Le site http://www.hotlinker.net/htpasswd.html permet aussi d'effectuer cette opération en ligne. Il ne reste alors plus qu'à faire un copier/coller versle fichier .htpasswd.

Le fichier final doit ressembler à ce qui suit :

john:{SHA}ny/rDx70JbKS8vlLyEgklN9DBBM=
richard:$apr1$6cDm4/..$PKCJpyjbBxD/6z.n.n81h.
ellaine:{SHA}uRTmG2uVa0vB8QX5av9U6wqSaiA=
ally:{SHA}/QQDbgFX9EUSDf/T9CRZ4h+0lz4=



Comment se prémunir contre les 'hotlinks'.

- Les hotlinks : présentation et exploitation.

Le web regorge de ressources éparpillées aux quatre coins du monde. Les liens, grace à qui voyager d'un site à l'autre s'effectue en toute transparence, sont les fondements meme de la toile. Pourtant, ces fameux liens se révèlent parfois d'une trop grande transparence. Prenons l'exemple d'une simple image. Au milieu du code HTML composant la page web proprement dite, elle est forcément symbolisée par un lien. Defait, l'image en question peut provenir du meme serveur, ou bien etre localisée sur un site distant. Pour le client, le résultat est identique :il voit l'image et non la source (certes, il pourrait identifier la source,mais combien de visiteurs prennent de telles precautions?) . Là réside tout le problème du "hotlink" : le droit au lien sur une ressource n'est pas forcément voulu par le propriétaire de celle-ci. Et pourtant,c'est lui qui devra fournir le contenu et la bande passante, bien que le site le présentant puisse appartenir à un concurrent direct. Concrètement, les moyens d'effectuer des "hotlinks" sont nombreux : - Référence directe à une image :

<img src="http://ressource.externe">

- Simple lien :

<a href="http://ressource.externe"> <imgsrc="http://serveur.réel"></a>

.
Par exemple, le serveur réel peut présenter une image réduite d'une vidéo. Mais lorsque le visiteur va cliquer sur cette image pour télécharger la vidéo complète, le transfert s'effectuera à partir d'un serveur tiers.
- Javascript. - Frames (idéales pour faire croire à un visiteur qu'il est toujours sur lememe site) .

- DHTML. Il est pourtant essentiel qu'un site soit protégé contre les liens non autorisés. Une vidéo "hotlinkée" par différents sites risque de rapidement écrouler le serveur hébergeant celle-ci. Pourtant, aucun des visiteurs n'aura pris connaissance de son site originel ! Le manque à gagner est donc réel.


Le mythe du "Referer".


Lorsqu'un client web se connecte à un site, il est censé transmettre au serveur un "refefer", qui caractérise la page précédente sur lequel se trouvait le visiteur. Plus exactement, le champs "referer" des requetes HTTP effectuées par un client web peut contenir la page où se situe le lien qui a conduit à la page demandée.
Une idée pour éviter les hotlinks consiste donc à tester ce "referer" et à refuser toute connexion en provenance d'un site inconnu. On peut effectuer ceci dans un fichier .htaccess . Pour citer la FAQ officielle du groupe de discussion de référence pour les webmasters, "alt.www.webmaster", disponiblesur http://www.aww-faq.org : How can I stop someone from hot-linking to my images?

You can use .htaccess if you are using mod_rewrite. Add the following to.htaccess :

RewriteEngine on
RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} !^http://domain.com/.*$ [NC]
RewriteCond %{HTTP_REFERER} !^ http://www.domain.com/.*$ [NC]
RewriteRule .*\.gif$ - [F]
RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} !^http://domain.com/.*$ [NC]
RewriteCond %{HTTP_REFERER} !^ http://www.domain.com/.*$ [NC]
RewriteRule . *\.jpg$ - [F]>>


Ces lignes ont pour effet d'interdire l'envoi d'images gif et jpg si le referer n'est pas domain.com,lorsque le referer n'existe pas, l'acces est malgré tout autorisé (faute de quoi le site serait inaccessible derriere certains firewalls ou avec certains brouteurs. De meme, cette precaution est indispensable pour que les visiteurs puissent ajouter les pages dans leurs listes de favoris). Beaucoup de webmasters ont recopié ces quelques lignes sans meme lire la suite, pourtant fort intéressante. <<Please note that this sort of protection is very weak. Hotlinking will still work if the linking site is on an SSL encrypted page, because all clients clear the referer when an HTTP page is called from an HTTPS one. Also, clients can use simple personal proxies that transparently rewrite referers to match your rules, in order to bypass all these filters. An example is Hotlinker (www.hotlinker.net). These tricks are already widely used for porn sites. The best way to go is to use cookies (like PHPsessions) or cryptography.>> En résumé :  - Tout site utilisant le protocole HTTPS peut librement effectuer des liens car lorsque le brouteur vient d'un tel site, le 'referer' est volontairement retiré, afin de ne jamais transmettre d'éventuelles informations confidentielles. Un autre intéret du protocole HTTPS est qu'il n'est pas pris en charge par les moteurs de recherche. Il devient ainsi très difficile, pour un site hotlinké, d'en déceler l'origine. C'est pourquoi on trouve de plus en plus de sites TGP officieux en HTTPS, bien qu'ils n'y pratiquent aucun commerce électronique. - Vu que le client web fixe lui-meme le contenu du referer, il peut tout à fait le modifier à sa guise. Des petits programmes s'en chargent d'ailleurs très bien et recopient simplement le nom du site dont fait partie le lien. Le referer est donc toujours valide. Ajoutons à cela que l'utilisation du module mod_rewrite d'Apache a connu de sérieux problèmes de sécurité et augmente forcément la charge d'un serveur. Le referer n'est donc qu'indicatif. Il peut etre intéressant lors d'analyses statistiques, mais il doit définitivement etre écarté pour tout besoin d'authentification ou de vérification.


Les identifiants uniques.

-
L'envoi de cookies. Nous devons donc trouver un moyen d'identifier un visiteur et de s'assurer qu'avant de télécharger un fichier, il est bien passé par un hemin"conventionnel". En l'occurrence par les pages du site où se situent les liens vers ce fichier. Une première approche, assez simple, consiste à employer des cookies. Nous allons l'illustrer avec un site fictif, www.42.sex . Le déroulement des opérations est le suivant : - Le visiteur se connecte sur le site http://www.42.sex . - Une valeur aléatoire est générée. On la transmet au client qui va la conserver sous la forme d'un cookie. Coté serveur, on mémorise aussi la valeur. - Avant d'envoyer un fichier susceptible d'etre hotlinké, on vérifie que le cookie reçu soit présent dans la base des valeurs précédemment envoyées.Dans le cas contraire, le fichier est hotlinké. Les client peut alors librement accéder au site, et meme enregistrer les liens dans ses favoris sans aucun problème.

Inconvénients du système : - Si le client efface ses cookies, il devra repasser par la case départ pour obtenir un nouveau cookie. - Tous les cookies doivent etre conservées sur le serveur. Cela prend de l'espace disque, et un petit malin peut demander un grand nombre de cookies au serveur jusqu'à saturation de l'espace.

- Les cookies ne sont pas toujours bien tolérés par les visiteurs, car ce sont avant tout des mouchards. - Dès l'instant où un visiteur a un cookie valide pour un site, les hotlinks vers ce site deviennent possibles pour lui. En pratique, les risques sont minimes car cette situation se rencontre très rarement.


Un exemple d'implémentation en PHP.


Voici un exemple, en PHP, d'implémentation de la méthode anti-hotlinks présentée ci-dessus.

Pour en tirer partie, il suffit d'organiser son site en séparant son contenu(pages HTML, photos, vidéos, fichiers à télécharger...) en deux catégories :

  • Celles qui ne présentent aucun risque à etre liées, telles que les pages d'accueil.
  • Celles qui doivent au contraire n'etre accessible que si l'une des pages précédentes a préalablement été visitée.
Les pages de la première catégorie vont avoir pour but d'envoyer un cookie au client, si celui-ci n'en dispose pas encore. Pour cela, on dispose des fonctions withcookie() et send_withcookie() définies dans le listing précédent. La premiere envoie un cookie au client si celui-ci n'en dispose pas encore. La seconde est identique, mais transmet en plus le contenu d'un fichier. Les pages de la seconde catégorie vont d'abord valider la présence du cookie avant d'envoyer tout contenu. Pour cela, nous avons défini deux fonctions : checkcookie() qui se contente d'effectuer une vérification, etsend_checkcookie() qui envoit le contenu d'un fichier après vérification. Voyons comment transformer un site traditionnel en un site protégé contre les hotlinks à l'aide de ces fonctions. Nous allons partir d'un site traditionnel, dont la structure est la suivante : - /index.html : page d'accueil. - /videos.html : la page presentant les videos disponibles sur le site. - /videos/video1.mpeg et /videos/video2.mpeg : deux videos.

But du jeu : interdire l'acces a la page des videos et aux videos proprement dites, sauf si la page d'accueil a préalablement été visitée. La première chose à faire est de créer un répertoire dont l'accès par le web sera totalement interdit. Le répertoire peut etre situé en dehors de la hiérarchie des pages web, ou bien etre protégé par un fichier .htaccess .Dans notre exemple, ce répertoire va etre /private.

Nous allons y placer un premier fichier, nommé antilink.php, avec le contenudu précédent listing. Il contient toutes les fonctions à réutiliser par la suite.

Le fichier index.html va ensuite etre renommé index.php. Deux modifications vont etre apportées à son contenu : - Le lien vers videos.html va etre remplacé par un lien vers videos.php .

- Les lignes suivantes vont etre ajoutées tout au début du fichier :

<script language="php">require('../private/antilink.php'); withcookie();</script>

Le but de ces ligne est simplement d'envoyer un cookie au client. Celui-ci est en effet indispensable pour qu'il puisse visiter les pages suivantes. Ensuite, le fichier videos.html va à son tour etre renommé videos.php . Là encore, deux modifications sont à apporter : - Les liens vers /videos/video1.mpeg et /videos/video2.mpeg vont etre remplacés par des liens vers /videos/video1.php et /videos/video2.php .

 

- Les lignes suivantes vont etre ajoutées au début :

<script language="php">require('../private/antilink.php'); checkcookie();</script>

Ces lignes vérifient la présence d'un cookie valide. Dans le cas contraire, le contenu de la page n'est pas affiché. Si le contenu du répertoire /videos est librement accessible, aucune protection contre les hotlinks n'est possible. C'est pourquoi nous allons déplacer toutes les vidéos vers un répertoire privé, par exemple le répertoire /private. L'astuce consiste en effet à défendre au client d'y accéder sans passer par un script PHP vérifiant les cookies. C'est pourquoi nous allons placer dans le répertoire /videos deux scripts, video1.php et video2.php. Ceux-ci vont simplement appeler la fonction send_checkcookie(), qui controle les cookies puis, si tout semble en règle, envoit le contenu d'un fichier (ici : une vidéo) .

Pour le visiteur, cela ne fait aucune différence. Bien que le lien pointe vers un fichier '.php', son brouteur va bien comprendre qu'il s'agit d'une vidéo. Pourquoi? Parce que sur le web, un fichier n'est jamais transmis sans préalablement en préciser la nature. Notre fonction send_checkcookie() va donc attendre deux arguments : le type de fichier, et son nom. Voici quelques valeurs possibles pour le type, dont les noms parlent d'eux memes :

audio/mpegimage/gifimage/pngimage/
jpegtext/htmltext/plaintext/cssvideo/mpegvideo/ quicktimevideo/x-msvideovideo/vnd.rn-realvideo


Voici donc à quoi va ressembler le fichier videos/video1.php : <script language="php">require('../../private/antilink.php' );send_checkcookie('video/mpeg', '../../private/video1 .mpeg');</script>

Le fichier videos/video2.php est bien entendu à créer de façon analogue.

La cryptographie : une autre approche de la lutte contre les hotlinks.

L'approche précédente a le mérite d'etre simple à mettre en oeuvre. La migration d'un site classique vers cette architecture protégée ne demandepas énormément de temps. Une autre approche est néanmoins fort intéressante : la cryptographie. En voici les avantages : - Aucun espace disque nécessaire pour un nombre illimité de visiteurs distincts. - Cette solution fonctionne sans cookie. - La visite peut s'effectuer avec différents brouteurs sans perte d'authentification. - Meme après avoir visité un site dans les règles, il est impossible d'yeffectuer des hotlinks à partir d'autressites (contrairement à la méthodedes cookies) .

- Conséquence directe : le site ne peut etre la cible d'un cross-scripting.C'est une arme efficace pour éviter la triche sur des outils de vote. Et du coté des inconvénients : - La méthode présentée ici se base sur l'adresse IP du client. S'il ne dispose pas d'une IP fixe, l'enregistrement d'une page protégée dans les favoris ne fonctionnera pas. - Le déploiement est un peu plus complexe que celui de la méthode par cookie. Mieux vaut adapter dès le départ son site à une protection cryptographique. Le principe est d'attribuer des adresses personnalisés à chaque client.Ainsi, pour atteindre une meme image, deux personnes devront se rendre à des URL totalement différentes, et non interchangeables. Les hotlinks deviennent de ce fait impossible, puisqu'un lien effectué par un webmaster ne serait valide que... pour sa propre machine.

La protection repose sur les fonctions à sens unique, que nous avons déjà évoquées pour les mots de passe. Soit F une telle fonction (qui peut etreMD5, SHA1, RMD160, ...) . Si l'on calcule F(X), on obtient un nombre caractéristique de X, mais à partir duquel il est impossible de retrouver X sans essayer toutes les possibilités (ce qui peut prendre un temps colossal avec des fonctions lentes dont le résultat est sur 160 bits) . Mais il n'y a bien entendu qu'un seul résultat possible pour F(X) .

Imaginons maintenant le scénario suivant : - Le client demande à charger la page d'accueil. - Le serveur connait l'adresse IP de tous les clients qui s'y connectent. Il calcule F(IP) et, dans la page d'accueil, il ajoute '&key=<xxxxx>' après chaque lien (<xxxxx> étant le résultat de F(IP)) . - Lorsque le client va cliquer sur un lie n, il va transmettre une valeur qui le caractérise, ici l'application d'une fonction à son adresse IP. Le serveur connait l'adresse IP du client et peut recalculer F(IP) à tout moment, et comparer le résultat avec la valeur de 'key' envoyée par le client. Si les valeurs diffèrent, il y a clairement un problème : le client n'a pas renvoyé la valeur initialement proposée par le serveur. Nous avons donc affaire à un hotlink, car le lien ne peut provenir du serveur d'origine. Cette méthode est néanmoins très limitée, car si F est connue du client, il peut recalculer F(IP) sans problème. Le hotlink devient alors possible, car le site responsable du hotlink peut regénérer les liens à la volée, d'après l'adresse IP du visiteur. Nous allons rendre cela impossible en ajoutant une clef secrete à l'adresse IP. C'est à dire qu'au lieu d'envoyer F(IP), le serveur web va calculer F(<abcdef> (+) IP) . <abcdef> est un nombre secret, présent sur le serveur, mais qui ne va jamais etre transmis aux clients. Cette clef secrète étant fixe, le serveur est toujours en mesure de recalculer la clef d'authentification. En revanche, cette opération devient impossible pour un serveur tiers, qui peut disposer de l'adresse IP du client, mais pas de la clef du serveur d'origine. Le hotlink est donc impossible. Pour compliquer les choses, nous pouvons faire en sorte que deux visites sur le meme site d'un meme client (à partir d'une meme adresse IP) provoque malgré tout un échange de clefs totallement différentes. Cela en ajoutant une "graine" aléatoire : la clef d'authentification devient alors F(<valeuraléatoire> (+) <abcdef> (+) IP) . Pour que le serveur puisse recalculer la clef par la suite, la valeur aléatoire doit en revanche obligatoirement etre transmise dans les liens, au meme titre que la clef. La seule difficulté de ce procédé consiste à rendre toutes les pages HTML dynamiques puisque les liens doivent etre calculés en fonction du client.Pour y parvenir, on peut mélanger PHP et HTML :

<script language="php">echo '<a href="/videos/ video1.php?key=' . urlencode($key) . '">';</script> <img src="thumbnail.jpg" alt="sous la douche" /></a>

On peut aussi écrire des pages HTML traditionnelles, mais comportant des balises qui seront dynamiquement remplacées par la clef. Ainsi,'videos.html' sera dans un répertoire inaccessible, mais 'videos.php' va charger ce fichier, remplacer les balises par la clef, et afficher le résultat. Une implémentation complète de cette technique, baptisée Antilink, est disponible à l'adresse suivante :

ftp://ftp.fr.pureftpd.org/pure-ftpd/antilink/ Elle est écrite en langage C (mais se destine uniquement aux systèmes Unix),utilise la fonction SHA1 et effectue les substitutions de balises. Les clefs d'authentification sont calculées d'après l'adresse IP, une graine de 64bits et une clef secrète de 1024 bits. Elle comporte quatre programmes utilisant l'interface CGI, compatible avec n'importe quel serveur web : - antilink-sendkey.cgi : envoit le contenu d'un fichier et la clef d'authentification au client. - antilink-checkkey.cgi : vérifie la validité de la clef envoyée par le client, charge un fichier, substitue la clef à la balise <KEY /> et envoit le résultat. - antilink-checkkey-raw.cgi : vérifie la validité de la clef et envoie le contenu d'un fichier sans substitution (par exemple pour une image, une vidéo...) . - antilink-checkkey-cgi.cgi : lance un script CGI quelconque après avoir vérifie la validité de la clef. A l'heure où ces lignes sont écrites, Antilink fonctionne parfaitement, mais manque cruellement de documentation et n'est peut-etre pas très aisé à installer. Nous y reviendrons donc dans le prochain numéro d'ABV, exemples à l'appui, éventuellement complétés d'une implémentation plus simple en PHP. - Introduction à la programmation sécurisée. A la base de tout site dynamique se trouvent des scripts. Qu'ils soient écrits en Perl, en PHP, en Pike, en Python, en Shell, ou en OCaml, ils ont tous le meme but : générer un contenu d'après un ensemble de données,combinées aux requetes effectuées par les clients. Ce dernier élément est particulièrement sensible. En fonction des URL choisies, des cookies échangés, des cases cochées ou des formulaires remplis, les scripts vont effectuer un traitement spécifique. Dans la plupart des cas, le traitement suit la procédure logique établie par le programmeur. Mais que se passe-t-il en cas de bogue? Et à plus forte raison si le client choisit volontairement des paramètres destinés à faire ressortir ces bogues? Dans le meilleur des cas, le visiteur obtient un message d'erreur. Dans le pire des cas, le visiteur a pris le controle de votre serveur. Voici donc quelques conseils pour éviter les erreurs les plus basiques, mais qui sont malheureusement aussi les plus fréquentes.

Les valeurs aléatoires.

En informatique, la notion de valeurs aléatoires est très subjective. Ces valeurs proviennent en effet toujours du résultat de fonctions mathématiques. Et dès l'instant où les paramètres de ces fonctions sont connues, les valeurs sont évidemment totalement prévisibles. Pour une utilisation courante (sélection aléatoire de bannières, répartition de charge, ...) une suite prévisible de valeurs aléatoires n'est pas très génante. En revanche, pour du commerce électronique, des jeux primés ou toute forme d'authentification, il est hors de question de s'en tenir à un générateur de nombre pseudo-aléatoires. Il faut donc choisir des sources d'entropie particulièrement imprévisibles.


La date : une source intemporelle d'entropie.


Dans quasiment tous les langages de programmation se trouve une fonction destinée à générer des nombres pseudo-aléatoires. Elle fait appel à une fonction mathématique dont la répartition du résultat est (ou devrait etre) uniforme. Lorsqu'une nouvelle valeur pseudo-aléatoire doit etre tirée, on calcule F(n+o), ou 'n' est le nombre de tirages effectués par le script courant, et 'o' une graine, destinée à ce que deux invocations du meme programme donnent des résultats différents. 'n' est généralement très faible. Si une seule valeur aléatoire est tirée (par exemple pour envoyer un cookie), 'n' sera meme toujours nul. La difficulté de prédire les valeurs aléatoires à venir ne dépend donc que d'un seul facteur : 'o'. Il doit donc sans cesse changer pour etre une source d'entropie suffisante. Et c'est là où le bat blesse : la plupart des programmeurs utilisent simplement la date courante comme graine avec des fragments de code source tels que :
srand(time()); C'est une très mauvaise idée, pour deux raisons :

- ainsi lue, la date a une précision maximale d'une seconde. Deux connexions successives auront par exemple le meme cookie.

- il est trivial de deviner la graine, meme avec unéchantillon de valeurs pseudo-aléatoires très réduit, les machines étant censées etre à l'heure. La documentation de PHP conseille d'y ajouter les fractions de secondes, à l'aide de la fonction microtime() :


function make_seed() { list($usec, $sec) = explode(' ', microtime()); return (float) $sec + ((float) $usec * 100000);}srand(make_seed());


Un traitement similaire peut etre effectué dans les autres langages (par exemple à l'aide de syscall(&SYS_gettimeofday...) en Perl, gettimeofday() en C) . Malheureusement, cette méthode reste loin d'etre infaillible. Selon les systèmes, la précision de l'horloge varie. Elle n'est parfois que de deux secondes, ce qui rend la fonction microtime() guère plus fiable que time() . Pour y pallier, les systèmes d'exploitation modernes disposent de générateurs de nombres aléatoires plus surs, dont la graine est fixée au démarrage du système. 'n' (le nombre de tirage) est incrémenté à chaque consultation du générateur quelqu'en soit le programme appellant. On y accède en lisant simplement le contenu d'un fichier, chaque byte lu étant aléatoire. Les sources d'entropie employées par le système pour ces générateurs peuvent etre très variées : - Traffic réseau (bien que ce soit une source souvent contestée par les puristes) . - Date du dernier reboot. - Déplacements de la souris, touches frappées au clavier. - Etat matériel : interruptions, contenu des registres, ... - Sources imprévisibles : radioactivité, mouvements des électrons, ... La méthode la plus courante consiste à échantillonner deux diodes Zener différentes (valeur '1' au delà d'un certain seuil, 0 dans le cas contraire) et à les combiner par une porte logique pour obtenir un signal binaire imprévisible (en général une porte AND suivie d'une porte NOT pour éviter le cas où les deux diodes ont excédé le seuil simultanément à cause de facteurs externes) . Les cartes-mères telles que celles basées sur un chipset i810 disposent d'un tel circuit, mais tous les systèmes d'exploitation n'en tirent pas forcément profit. Pour accéder aux valeurs aléatoires, on dispose de plusieurs fichiers, certains n'étant pas présents sur tous les systèmes, ou nécessitant l'installation d'un module annexe (exemple: Solaris) : - /dev/srandom : c'est le générateur le plus lent, mais le plus sur. Il ne se base que sur des sources d'entropie fiable et va attendre que des données soient disponibles si nécessaire. Les données ne sont de plus jamais directement transmises sans passer par une fonction à sens unique (souventMD5) . - /dev/random : c'est soit une interface vers les modules matériels de génération de nombres aléatoires, soit l'équivalent de /dev/srandom. C'est donc aussi une source sure. - /dev/arandom : identique à /dev/srandom, mais dont la rapidité est garantie : lorsqu'il n'y a plus de données disponibles dans une source d'entropie, on réalimente le générateur de nombre aléatoires à l'aide des résultats précédents auquels on applique une fonction tels qu'un RC4./dev/arandom est le meilleur compromis sécurité/rapidité, fiable aussi bien pour la génération de certificats que pour une utilisation intense (ex: génération de cookies) . - /dev/urandom : générateur très rapide, mais moins sur que les précédents.Lorsqu'il n'y a plus de données dans la source d'entropie, la suite est extrapolée. Pour le système anti-hotlinks à base de cookies présenté plus haut,ce générateur est suffisant car un cookie ne peut de toutes façons etre attribué qu'à partir du domaine qui le concerne. - /dev/prandom : le plus rapide des générateurs, basé sur une graine et une simple fonction. Il ne garantie en revanche aucune sécurité. Voici une simple fonction PHP retournant un byte aléatoire (en principe entre 0 et 255) à l'aide de ces interfaces, ou -1 en cas d'erreur :


function getrandbyte() { if (($rd = fopen('/dev/arandom', 'rb')) == FALSE) { return -1; } $v = fread($rd, 1); fclose($rd); if (strlen($v) != 1) { return -1; } return ord($v);}

Essayez cette fonction avec les différents générateurs (/dev/random,/dev/urandom, ...) . Si la fonction renvoit systématiquement -1 avec l'un d'entre eux, c'est que le système hébergeant le serveur web ne l'implémente pas. Si le système ne dispose pas de /dev/arandom, que /dev/srandom (ou/dev/random) se révèle trop lent, et que l'on a malgré tout besoin de valeurs sures, une solution consiste à mélanger plusieurs sources non sures, mais distinctes, par exemple /dev/urandom et un appel au générateur classique (par exemple rand(), après en avoir initialisé la graine) :

function getrandbyte2() { if (($v = getrandbyte()) == -1) { return -1; } return hexdec(substr(md5($v . rand()), 0, 2));}


Les sessions PHP.

L'une des facilités les plus appréciées du langage PHP est la possibilité qu'il offre de sauvegarder un ensemble de variables. Cet ensemble est identifié par un nombre unique, qu'il est simple de passer ensuite au client pour conserver le contenu des variables d'un lien à l'autre. Les variables peuvent etre stockées de différentes façons : - Dans de simples fichiers. C'est le cas le plus courant. - En mémoire partagée. Cette solution est très rapide, mais malheureusement pas très fiable avec les versions actuelles de PHP. - Dans une base SQL, ce qui peut hélas se révéler assez lent. Chez la plupart des hébergeurs, c'est la première solution qui est retenue par défaut. A chaque session PHP, un fichier est crée. Et faute de consignes adéquates, les fichiers de tous les clients d'un serveur mutualisé sont stockés dans un unique répertoire. Deux problèmes se présente alors : - Beaucoup de systèmes de fichiers voient leurs performances descendre en flèche lorsqu'il s'agit de naviguer à l'intérieur d'un répertoire comportant beaucoup d'entrées. De fait, l'accès aux sites est considérablement ralenti.  - Ce répertoire partagé (généralement /tmp) est souvent lisible par tous les comptes d'un serveur mutualisé. Ce qui signifie qu'un client peut voler les sessions de tous les autres sites. Autre problème couremment rencontré avec les sessions PHP : la prédicabilitéde ceux-ci. Comme nous venons de le voir ci-dessus, un générateur de nombre aléatoires doit produire des résultats imprévisibles. C'est d'autant plus vrai lorsque les variables d'une session peuvent contenir des mots de passe, des coordonnées ou des commandes en cours.Par défaut, celui de PHP n'est malheureusement pas sur, car il se base simplement sur la date. Nous allons remédier à tous ces problèmes concernant les sessions en prenant deux mesures : - En indiquant à PHP d'employer une source fiable comme /dev/arandom. - En stockant les fichiers dans un répertoire dédié au site concerné. Pour compléter, nous allons demander à PHP de vérifier assez souvent si de vieux fichiers de session ne seraient pas bons pour la poubelle. Cela évite de sérieux ralentissements sur les sites recevant beaucoup de traffic. Pour ce faire, les lignes suivantes sont à adapter et à ajouter au début d'un fichier PHP exploitant les sessions

:
ini_alter("session.entropy_file", "/dev/arandom"); ini_alter("session.entropy_length", "16");ini_alter ("session.gc_probability", "42");session_save_path ("/home/john/cookies");

Le répertoire de sauvegarde (ici "/home/john/cookies") doit etre préalablement crée, et il doit etre accessible en lecture et écriture par l'utilisateur sous lequel les scripts PHP sont exécutés. En principe ils'agit de vous-meme. Vous pouvez alors retirer les droits d'accès aux autres utilisateurs.



Les variables externes.


En dehors des sessions, PHP disposait d'une facilité très employée pour accéder aux variables transmises par un client : une copie de celles-ci étaient stockée dans des variables globales. Ainsi, le contenu du champs PRENOM d'un formulaire était accessible comme une simple variable nommée $PRENOM. Ce fut une idée fort regrettable, car une utilisation imprudente de ce mécanisme a conduit des centaines de scripts à posséder des failles de sécurité triviales à mettre en oeuvre. Prenons l'exemple d'une variable 'user_ok' dont la valeur serait TRUE après authentification réussie de l'utilisateur :

if (user_auth()) { user_ok = TRUE;}

Rien n'empeche un utilisateur malveillant d'accéder au site en passant une variable 'user_ok' avec le contenu qu'il désire. Par exemple simplement en ajoutant '&user_ok=1' à l'URL à laquelle il se rend. Résultat : l'utilisateur va pouvoir naviguer sur le site sans authentification préalable. Autre exemple courant : si une session conserve le nom du visiteur connecté dans une telle variable, rien ne l'empèche de modifier cette variable pour prendre l'identité de quelqu'un d'autre. Pour cette raison, depuis la version 4.1.0 de PHP, ce comportement est désactivé par défaut. Libre à l'hébergeur de l'activer explicitement pour conserver une compatibilité ascendante avec les scripts mal écrits (et c'est malheureusement le choix qui est effectué la plupart du temps) . Mais il est prévu à court terme de retirer totalement cette fonctionnalité de l'interpréteur PHP. Pour accéder à une variable en provenance d'un client web, on doit désormais impérativement faire appel à quatre tableaux en PHP : - $_GET : qui contient toutes les variables passées parla méthode 'GET'. - $_POST : qui contient toutes les variables passées par la méthode 'POST'. - $_COOKIE : qui contient les cookies. - $_REQUEST : qui contient toutes les informations des trois tableaux précédents. Il regroupe donc toutesles variables envoyées par le client,que celui-ci est susceptible de modifier à sa guise. De cette façon, les variables clients sont totalement distinctes des variables globales qui doivent rester internes au script PHP. Voici une simple page HTML comportant un formulaire :


<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2//EN"> <html> <head> <title>Formulaire</title> </head> <body> <form action="getemail.php" method="post"> <input type="text" name="email" size="32"> <input type="submit"> </form> </body></html>


Nous disposons ici d'une variable cliente 'email' envoyée par la méthode'POST'. Voici donc comment y accéderdans un script PHP :


$email = $_POST['email'];



L'interruption de scripts PHP.

Une chose est à savoir : si un visiteur appuie sur le bouton 'Stop' de son brouteur pendant l'exécution d'un script PHP, et que ce script a la bonne idée d'essayer ensuite d'envoyer la moindre donnée au client, le script va prendre immédiatement fin. S'il restait des requetes SQL importantes à effectuer (exemple: enregistrement de l'IP du client après avoir pris encompte un vote), elle ne seront malheureusement jamais lancées. Si des fichiers temporaires ont été crées, ils ne seront pas effacés. Nous allons ici présenter une solution en PHP, mais tous les autres langagesde scripts ont le meme comportement. En Perl ou en C, il faudra par exemple interceper les signaux SIGPIPE et SIGKILL pour éviter tout désagréments. PHP dispose d'une fonction fort méconnue et pourtant indispensable dans ce type de situation : register_shutdown_function() . Son but est d'enregistrer une fonction qui sera dans tous les cas appellée à la fin d'un script PHP,que celui-ci ait pris fin de façon toute à fait normale, ou qu'il ait été plus violemment interrompu. Plutot que d'employer la structure suivante : - ouverture de bases, création de fichiers temporaires, allocation de mémoire. - traitement. - libération de mémoire, effacement des fichiers temporaires, fermeture debases. Il est infiniment plus fiable de commencer par enregistrer la fonction chargée du nettoyage des opérations, qui sera forcément appelée au moment propice : - enregistrement de la fonction qui libere la mémoire, efface les fichiers temporaires et ferme les bases. - ouverture de bases, création de fichiers temporaires, allocation de mémoire. - traitement. Ainsi, meme si le client met prématurément fin à une connexion (que ce soit en cliquant sur Stop ou suite à des problèmes réseau), tout reste cohérent toujours coté serveur. Voici un simple extrait de code source qui annule la transaction MySQL encours si le script a été interrompu avant la fin du traitement :

<script language="php"> # Fonction de 'nettoyage' appelée à la fin du script (meme si celui-ci a été# interrompu par le client) . function cleanup() { global $sql_ok; global $sql_id; if (!isset($sql_id)) { return; } if ($sql_ok != FALSE) { mysql_unbuffered_query('ROLLBACK', $sql_id); } mysql_close($sql_id);} # sql_ok indique s'il est nécessaire d'effectuer ou non un rollback $sql_ok = FALSE; # Enregistrement de la fonction de nettoyage. register_shutdown_function('cleanup'); # Script proprement dit. if (($sql_id = mysql_pconnect ('sql', getenv('SQL_USER'), getenv ('SQL_PASSWORD'))) == FALSE) { echo mysql_error(); exit;} mysql_unbuffered_query('SET AUTOCOMMIT=0', $sql_id); # ... divers traitements, affichages et requetes ... $sql_ok = TRUE; </script>



Les dangers du cross-scripting.


Présentation du cross-scripting (CSS).


L'attaque concernant les sites web la plus en vogue actuellement se cache derriere une abbréviation de trois lettres : CSS, pour "cross-scripting"(sans rapport avec les feuilles de style) . Et pour cause : tous les sites sont potentiellement vulnérables, indépendemment des scripts, des logiciels,des systèmes et du matériel sur lesquels ils tournent. Le cross-scriptingad met aussi un grand nombre de variantes, et de nouvelles sont découvertes chaque jour. Quelques paragraphes se révèlent donc bien maigres pour cerner ce problème, mais nous allons en décrire les principes afin de sensibiliser les webmasters. Le problème est sérieux puisque meme Microsoft, Netscape,Yahoo, CNN et Google en ont récemment subit les facheuses conséquences.

Prenons l'exemple d'un forum de discussion. Chacun est libre d'y poster des messages publiquement consultables. Pour agrémenter ceux-ci, toutes les balises HTML sont autorisées. Les visiteurs peuvent ainsi placer des images, des effets de style et... des scripts. Ce dernier point ouvre beaucoup de possibilités. Par exemple, on peut aisément écrire un javascript qui va ouvrir une connexion à l'adresse 'http://www.42.sex/<cookie>', où <cookie>est remplacé par un cookie placé par le forum. Le propriétaire du site 42.sex n'a plus qu'a consulter ses fichiers d'historique pour connaitre les cookies des visiteurs du forum, et se connecter sous leur identité. Toutes les variables peuvent ainsi etre transmises. Il est aussi courant d'ouvrir ainsi des popups vers le site d'origine pour que tout client visualisant le forum devienne aussitot inutilisable, tout en chargeant simultanément le serveur. Le javascript peut aussi contenir des adresses de serveurs privés qui ne feront aucune différence pour les utilisateurs piégés.

Bien, il suffirait donc de retirer les balises permettantl'exécution de scripts pour etre à l'abris de telles attaques? Que nenni, le cross-scripting ouvre bien d'autres portes. Soit http://www.42.sex un site permettant de voter pour ses sites préférés. Les sites qui y sont référencés vont n'avoir qu'un seul but : se placer en haut du classement. Seulement voilà : un seul vote par adresse IP est autorisé. L'adresse exacte permettant d'enregistrer un vote pour le site 123 est http://www.42.sex/vote.pl?site=123 . Comment obliger un maximum de personnes à se rendre à cette adresse, en utilisant d'autres vulnérabilités du forum? D'apparence anodine, les liens vers des images ont pourtant cette faculté.Il suffit en effet d'inclure dans le message la balise suivante :

<img width="1" height="1" src="http://www.42.sex/vote.pl?site=123">


Pour que chaque personne visualisant le message se retrouve contre son gré à voter pour le site 123. Contre son gré et... sans s'en rendre compte puisqu'à l'écran, en dehors d'un imperceptible pixel, rien ne parait suspect. Bien... les scripts et les images doivent donc etre filtres. Est-ce enfin suffisant? Et non... Car bien entendu des résultats similaires peuvent etre obtenus avec les frames. Les balises <body> présentent donc aussi des risques. Le plus sur est donc de partir du principe qu'aucune balise n'est autorisée,et de tolérer explicitement celles qui ne présentent vraiment aucun danger(<b>, <em>, <font>, ...) . Nous avons illustré ceci avec l'exemple d'un forum, mais toutes les pages dont un utilisateur peut indirectement modifier le contenu est potentiellement vulnérable. A titre d'exemple, prenons un formulaire permettant à un visiteur de s'inscrire sur une liste de diffusion. Il y entre son nom, son prénom et son email. Ses coordonnées sont alors enregistrées sur le serveur et une page s'affiche avec un contenu semblable à ce qui suit : <<<Bonjour Richard Fish, votre abonnement a bien été enregistré.>>> Un site tiers peut tout à fait mettre en place un lien qui va pointer sur le script de traitement de ce site. Par exemple avec un lien comme celui-ci :


<a href="http://www.42.sex/abo_liste.pl? nom=Richard&prenom= Fish&email=rf@cagefish.fr"> ...</a>


Si le script n'accepte que la méthode POST, le site tiers peut tout à fait mettre en place un formulaire factice. Bien. Il est possible de s'inscrire à la liste de diffusion de 42.sex à partir d'un autre site. Où sont les risques ? Faute de protection, ils sont semblables à ceux du forum évoqués plus haut,car il suffit de placer des balises HTML dans les variables 'nom' ou' prenom' pour exploiter les memes failles (exécution de script, liens cachés, substitution de cookies...) .


Comment s'en protéger ?


Afin d'éviter les conséquences liées au cross-scripting, des protections doivent etre mises en place : - pour interdire l'affichage de balises HTML non autorisées, et ce quelqu'en soit la page. - pour interdire les liens directs sur des scripts sensibles à partir de sites externes. Le second point revient à éviter les hotlinks, avec les techniques présentées au début de cet article. Il n'y a en revanche aucune réponse universelle au premier point, si ce n'est un maximum de vigilance lors de l'écriture de scripts. La règle simple a toujours avoir en tete est : le serveur ne doit jamais etre en mesure d'envoyer à un client des balises en provenance d'un autre client. Un principe simple, mais parfois laborieux à appliquer à la lettre s'il n'a pas été pris en compte dès la conception.

 

Jedi