Cookies
Dans le nouveau monde du e-commerce, les cookies jouent un rôle essentiel car ils permettent aux sites web de reconnaître les clients qui leur ont déjà rendu visite et de les accueillir comme des oncles d’Amérique : ils offrent au webmestre un moyen de mémoriser les visiteurs. Le premier cookie est un morceau de texte, souvent un identificateur unique, contenu dans un en-tête HTTP. Vous pouvez configurer Apache pour qu’il les concocte et les envoie automatiquement mais ce n’est pas très dur de le faire soi-même et cela offre plus de contrôle sur ce qui se passe. Les modules CGI.pm et CGI::Cookie fournissent également de l’aide mais, comme d’habitude, nous pensons qu’il est préférable de rester aussi près que possible du mécanisme de base.
Le navigateur du client conserve une liste de cookies et de sites web et, lorsque l’utilisateur revient sur un site, il renvoie automatiquement le cookie associé à ce site, s’il n’a pas expiré. Si l’en-tête HTTP ne comporte pas de cookie, vous, en tant que webmestre, pouvez alors supposer qu’il s’agit d’une première visite ; s’il y en a un, vous pouvez relier le nom du site et l’identifiant contenu dans le cookie aux informations stockées lors de la dernière visite de ce navigateur. Lorsque nous nous rendons sur Amazon, par exemple, nous voyons apparaître le message « Bonjour, Peter -- ou Ben -- Laurie » car le système d’Amazon reconnaît le cookie intégré à notre requête HTTP par notre navigateur, qui a trouvé le cookie qu’Amazon nous a envoyé lors de notre dernière visite.
Un cookie est une chaîne de texte. Son contenu minimum est nom=valeur et il ne peut contenir ni point-virgule, ni virgule, ni espace (si vous avez absolument besoin de ces caractères, utilisez l’encodage d’URL que nous avons décrit plus haut). Un cookie pour notre site serait, par exemple, de la forme :
Butterthlies=8335562231
Butterthlies identifie le site web qui a produit ce cookie -- un serveur qui héberge plusieurs sites a besoin de cette information. 8335562231 est l’identifiant qui a été affecté à ce visiteur lors de sa dernière visite. Pour empêcher que des pirates outragent votre dignité en inventant des cookies appartenant à d’autres clients, vous devez produire un nombre aléatoire assez grand à partir d’un germe qui ne peut pas être découvert ou le protéger en le chiffrant.
Un cookie peut également contenir d’autres champs :
expires= DATE
expires précise la date et l’heure d’expiration du cookie. En l’absence de ce champ, le navigateur oubliera le cookie à la fin de la session. Le format est de la forme Mon, 27-Apr-2020 13:46:11 GMT ( GMT est la seule zone horaire autorisée). Si vous voulez que le cookie soit « permanent », choisissez une date très lointaine, bien que cela provoque quelques problèmes avec les différentes versions de Netscape. Le résumé suivant provient de la documentation d’Apache :
Les versions de Mozilla 3.x ne comprennent les années sur deux chiffres que jusqu’à 37 (2037). Mozilla 4.x les comprend jusqu’à 50 (2050) mais accepte également les années sur 4 chiffres, qui peuvent sûrement atteindre 9999. Le meilleur choix pour envoyer un cookie destiné à durer longtemps consiste donc à choisir l’année 37.
domain= NOM_DOMAINE
Le navigateur comparera la fin de NOM_DOMAINE avec l’URL du serveur : cela signifie que l’URL shipping.crate.acme.com correspond à acme.com et que l’arborescence de l’URL est lu de droite à gauche : d’abord .com, puis acme, puis crate...
path= CHEMIN
Si le domaine correspond, on recherche la correspondance du chemin, mais de gauche à droite, cette fois-ci : / correspond à n’importe quel chemin, /truc correspond à /trucmachin et à /truc/html.
secure
Le cookie ne sera envoyé que sur un canal sécurisé : pour l’instant, cela signifie donc SSL, tel que nous l’avons décrit au chapitre 11.
Les différents champs sont séparés par des points-virgules :
Butterthlies=8335562231; expires=Mon, 27-Apr-2020 13:46:11 GMT
Un cookie reçu apparaît dans la variable Perl $ENV{'HTTP_COOKIE'}. Si vous utilisez CGI.pm, vous pouvez le disséquer automatiquement ; sinon, vous devez le faire en utilisant les outils Perl habituels, identifier l’utilisateur et en faire ce que vous voulez.
Pour envoyer un cookie, on l’écrit dans un en-tête HTTP, avec le préfixe Set-Cookie :
Set-Cookie: Butterthlies=8335562231;expires=Mon, 27-Apr-2020 13:46:11 GMT
sans oublier le \n final qui termine la partie des en-têtes HTTP.
Il faut avouer que certaines personnes sont contre les cookies -- mais se soucient-elles que le serveur les reconnaisse et leur verse leur bière favorite lorsqu’ils demandent à boire ? Certains sites trouvent d’ailleurs judicieux d’annoncer dans leur politique de protection de la vie privée qu’ils ne les utilisent pas.
Cookies Apache
Si vous le souhaitez, vous pouvez laisser Apache gérer tout cela pour vous en utilisant les directives que nous allons présenter. À notre avis, les cookies Apache ne sont vraiment utiles que pour mémoriser les visiteurs d’un site -- pour une analyse après coup du fichier log.
Récapitulons : si un site produit des cookies et reçoit une requête d’un utilisateur dont le navigateur n’a pas envoyé un cookie, ce site en crée un puis l’envoie : le navigateur du client le stockera tant que CookieExpires n’a pas été atteint (voir plus loin) et l’enverra à chaque fois que l’utilisateur se connecte à ce site.
Cependant, tout ce que fait Apache consiste à stocker le cookie de l’utilisateur dans le fichier log concerné : c’est à vous de constater qu’il est là et d’en faire quelque chose. Cela impliquera nécessairement d’écrire un script (plutôt obscur car il doit parcourir les fichiers log). Autant alors créer vous-même le cookie dans votre script et oublier les directives qui suivent, ce sera sûrement plus facile.
CookieName
CookieName nom
Configuration du serveur, hôte virtuel, répertoire, .htaccess.
CookieName fixe le nom du cookie produit par le serveur. Par défaut, il s’agit de Apache. Ce nom peut contenir les caractères A-Z, a-z, 0-9, _, et -.
CookieLog
CookieLog fichier
Configuration du serveur, hôte virtuel.
CookieLog précise un nom de fichier relatif à la racine du serveur, ou seront inscrits les cookies. Généralement, on configure un champ avec LogFormat et on capture les cookies dans le fichier log central (voir le chapitre 10).
CookieTracking
CookieExpires date-expiration
CookieTracking [on|off]
Configuration du serveur, hôte virtuel, répertoire, .htaccess.
CookieExpires fixe une date d’expiration pour le cookie. Sans elle, il n’en a pas -- même dans un très lointain futur -- et cela signifie qu’il s’évaporera à la fin de la session. La date d’expiration peut être exprimée par un nombre de secondes ou par une chaîne comme "2 weeks 3 days 7 hours" (dans ce dernier cas, la chaîne doit être entre apostrophes doubles). Les périodes valides sont les suivantes :
years
months
weeks
hours
minutes
Le fichier de configuration
Notre fichier de configuration est le suivant :
User webuser
Group webgroup
ServerName my586
DocumentRoot /usr/www/APACHE3/site.first/htdocs
TransferLog logs/access_log
CookieName "my_apache_cookie"
CookieLog logs/CookieLog
CookieTracking on CookieExpires 10000
Dans le fichier log, nous trouvons les lignes suivantes :
192.168.123.1.5653981376312508 "GET / HTTP/1.1" [05/Feb/2001:12:31:52 +0000]
192.168.123.1.5653981376312508
"GET /catalog_summer.html HTTP/1.1" [05/Feb/2001:12:31:55 +0000]
192.168.123.1.5653981376312508 "GET /bench.jpg HTTP/1.1"
[05/Feb/2001:12:31:55 +0000]
192.168.123.1.5653981376312508 "GET /tree.jpg HTTP/1.1"
[05/Feb/2001:12:31:55 +0000]
192.168.123.1.5653981376312508 "GET /hen.jpg HTTP/1.1"
[05/Feb/2001:12:31:55 +0000]
192.168.123.1.5653981376312508 "GET /bath.jpg HTTP/1.1"
[05/Feb/2001:12:31:55 +0000]
Le nombre 5653981376312508 indiquant ici la valeur de l’identifiant placé par Apache dans le cookie du visiteur.
Courrier électronique
Parfois, un script CGI doit envoyer un courrier électronique. Si cela doit être via un lien cliqué par l’utilisateur, utilisez la construction HTML suivante :
<A HREF="mailto:administrator@butterthlies.com">
Cliquez ici pour envoyer un courrier à l’administrateur</A>
Lorsque ce lien sera sélectionné, le logiciel de courrier de l’utilisateur devrait se lancer avec l’adresse de destination déjà insérée.
Si vous voulez envoyer un courrier automatiquement, sans l’aide de l’utilisateur, ni même qu’il le sache, utilisez le programme sendmail d’Unix (voir man sendmail ) ou tout agent de transfert de courrier compatible. Pour l’appeler à partir de Perl ( A est un nom de fichier quelconque) :
open A, "| sendmail -t" or die "Impossible d’ouvrir sendmail : $!";
Un équivalent à sendmail pour Win32 se trouve sur http://pages.infinit.net/che/blat/blat_f.html (ces pages sont en français). Pour le télécharger, cliquez sur le lien :
Une version récente est ici.
Une autre solution, peut-être plus sûre, consiste à utiliser le module Mail::Mailer, disponible sur CPAN.
Le format d’un courrier électronique ressemble beaucoup à ce que vous voyez lorsque vous en composez un avec Netscape ou MSIR : les adresses du destinataire et des copies, le sujet et le message apparaissent sur des lignes séparées par un retour à la ligne (que vous produirez à l’aide du caractère \n. Placez le message dans une variable Perl :
$msg=qq(To:fred@hissite.com\nCC:bill@ailleurs.com\nSubject:
La fete de ce soir\n\nSois chez Jeanne à 20h00\n);
Faites bien attention au double \n, qui sépare les en-têtes du corps du message. Pour l’envoyer, faites :
print A $msg
close A or die "Impossible d’envoyer ce courrier : $!";
et c’est parti.
Moteurs de recherche et CGI
La plupart des webmestres se soucieront passionnément de l’indexation de leurs créations par les moteurs de recherche du Web, afin que des millions de visiteurs puissent partager les délices qu’ils offrent. À l’heure où nous écrivions ce livre, les moteurs de recherche étaient en butte à un bon nombre de critiques qui leur reproche d’être lents, peu précis, arbitraires et, souvent, totalement faux. L’une des plus fortes critiques prétend que les sites qui offrent un grand nombre de pages distinctes produites par des scripts à partir de bases de données (en d’autres termes, la majeure partie des sites importants de e-commerce) ne sont pas correctement indexés : selon une estimation, seule une page sur 500 serait trouvée. Ces pages invisibles forment ce que l’on appelle « le Web obscur ».
Pour son étude de juin 2000, Netcraft a visité à peu près 16 millions de sites. Au même moment, Google prétendait être le moteur de recherche le plus complet avec 2 millions de sites indexés : cela signifiait que, au mieux, seul un site sur neuf pouvaient être trouvé via le meilleur moteur de recherche. Prudemment, Google ne revendique désormais plus un nombre de sites mais prétend indexer 3 083 324 652 pages web. Comme l’étude de Netcraft de juin 2003 montrait 41 millions de sites ( http://www.netcraft.com/Survey/Reports/0306/ ), cela signifie qu’un site moyen n’a que 75 pages -- ce qui semble trop peu, et de loin, et qui suggère qu’un grand nombre de sites ne sont pas indexés du tout.
La raison semble provenir du fait que les moteurs de recherche passent le plus clair de leur temps et de leur énergie à lutter contre le « spam » -- tentatives de donner à des pages plus de crédit qu’elles n’en ont vraiment. Les spammers utilisaient les scripts CGI bien avant que les bases de données s’imposent sur le Web et les moteurs de recherche ont donc trouvé des moyens de détecter les scripts. Si leurs soupçons étaient justifiés, les sites suspects n’étaient pas indexés. Personne, en dehors des développeurs des moteurs de recherche, ne connaît la vérité exacte sur ce problème -- et ceux qui sont concernés ne le disent pas -- mais la mythologie prétend qu’ils n’aiment pas les URL contenant les caractères !, ?, ou les mots cgi-bin ou assimilé.
De nombreux systèmes de développement commerciaux se mettent ainsi eux-même en faute mais si vous écrivez vos propres scripts et que vous les servez avec Apache, vous pouvez produire des pages qui ne pourront pas être distinguées des pages statiques. Avec notre script script2_html et le fichier de configuration vus plus haut, l’astuce consiste à :
- Supprimer cgi-bin/ des attributs HREF ou ACTION. On mettra, par exemple :
<A HREF="/script2_html/base_complete">
Cliquez ici pour voir toute la base de données</A>
- Ajouter la ligne :
ScriptAliasMatch /script(.*) /usr/www/APACHE3/APACHE3/cgi-bin/script$1
à votre fichier de configuration. Cette ligne capture toutes les URL commençant par /script : la construction (.*) est une expression régulière de Perl, empruntée par Apache, qui signifie « rappelle-toi de tous les caractères situés après le mot script ». Ces caractères réapparaissent alors dans la variable $1 et sont donc ajoutés à la suite de /usr/www/APACHE3/APACHE3/cgi-bin/script.
Lorsque vous cliquez sur le lien, l’URL qui sera exécutée, et celle que verront les moteurs de recherche sera http://www.butterthlies.com/script2_html/base_complete. Les mots fatals cgi-bin auront disparu et rien ne permettra de voir que la page renvoyée n’est pas statique... à part les mots script ou base, qui peuvent également être considérés comme suspects, mais vous connaissez maintenant le principe.
En outre, la plupart des moteurs de recherche ne savent pas se dépêtrer des frames HTML. Comme de nombreuses pages web les utilisent, c’est dommage et l’on peut se demander si les moteurs de recherche vivent à la même époque que nous. Pour répondre à ce problème, il suffit de fournir une page d’accueil plus sobre et de placer dans un environnement <NOFRAMES> des liens vers toutes les pages que vous souhaitez voir indexées (consultez votre ouvrage de référence sur HTML). Un outil utile dans ce cas là est un navigateur vraiment vieux, ne comprenant pas les frames, afin de voir vos pages comme les verront les moteurs de recherche. En ce qui nous concerne, nous utilisons une version Windows 3.x de Mosaic du NCSA (vous pouvez la télécharger à partir de http://www.ncsa.uiuc.edu ).
Le marqueur <NOFRAMES> aura tendance à capter les moteurs de recherche, mais il n’est pas infaillible. Une meilleure méthode consiste à déterminer si le client essaie d’ouvrir robots.txt, qui est un fichier standard contenant des instructions pour les parties de votre site que consulteront les robots (consultez le didacticiel http://www.searchengineworld.com/robots/robots_tutorial.htm et le RFC http://www.robotstxt.org/wc/norobots-rfc.html ). Si le visiteur recherche robots.txt, vous pouvez supposer à coup sûr qu’il s’agit d’un robot et lui servir un plat simple.
Les moteurs de recherche ont tous leurs propres spécificités. Google, par exemple, note un site en fonction du nombre de pages qui ont un lien vers lui, ce qui a tendance à cacher l’information qui vous intéresse. Les moteurs vont et viennent à la vitesse de l’éclair : si vous êtes parti pour un long voyage, il est sûrement préférable d’enregistrer votre site auprès des plus importants et d’oublier tous ces problèmes. L’un des auteurs maintient un site sur une encyclopédie médicale ( http://www.medic-planet.com ) et enregistre les visites des moteurs de recherche : après un délai initial de trois mois pendant lesquels rien ne s’est passé et qu’il a vécu dans l’anxiété, il reçoit maintenant des visites de plusieurs robots tous les jours et un flot de visiteurs remarquablement constant au fil des mois.
Si vous voulez faire de gros efforts pour séduire les moteurs de recherche, consultez les sites http://searchengineforms.com et http://searchenginewatch.com.
Débogage
Déboguer les scripts CGI est une activité qui peut être pénible car, tant qu’ils ne fonctionnent pas bien, rien n’apparaît dans le navigateur. À chaque fois que vous le modifiez, il est conseillé de tester un script à partir de la ligne de commande avant de l’invoquer à partir du Web. Perl l’analysera et recherchera les erreurs de syntaxe avant de le lancer. Ces éventuels messages d’erreurs, qui se retrouveraient dans le fichier log des erreurs lorsque le script est lancé par Apache, vous éviterons bien des griefs.
De même, essayez les appels à MySQL à partir de la ligne de commande pour être sûr qu’ils fonctionnent avant de les intégrer dans un script.
Gardez un œil sur le fichier log des erreurs d’Apache : il vous donnera souvent de bons indices, bien qu’il puisse être étonnamment silencieux alors que les choses se passent vraiment mal. Une cause fréquente de ce silence est un mauvais appel à MySQL : le module DBI ne se termine jamais et votre script se fige sans donner aucune explication.
Du moment que vous produisez un en-tête HTTP, quelque chose (mais pas nécessairement ce que vous voulez) s’affichera généralement dans le navigateur. Vous pouvez utiliser ce fait pour déboguer vos scripts en affichant les variables ou en plaçant des messages comme JE SUIS EN 1<BR>, JE SUIS EN 2<BR>, ..., dans votre code pour que vous puissier trouver l’endroit précis de l’erreur ( <BR> est la commande HTML pour produire un retour à la ligne). Cela ne fonctionne pas toujours car ces messages peuvent apparaître aux mauvais endroits à l’écran, voire pas du tout, selon le degré de confusion dans lequel l’erreur a placé le navigateur. Vous pouvez également afficher dans error_log à partir de votre script :
print STDERR "problème\n";
ou :
warn "problème\n";
Si votre document HTML met en place des frames et que vous affichez tous ces messages sur la même page, ils n’apparaîtront pas. Cela peut être assez troublant.
Vous pouvez voir le code HTML qui a été envoyé à votre navigateur en plaçant le curseur sur la page, puis en cliquant avec le bouton droit de la souris et en choisissant « Voir la source » (ou équivalent, selon votre navigateur).
Lorsque l’on travaille avec une base de données, il est souvent utile d’afficher le contenu de la variable $query avant de l’exécuter. Il faut savoir que bien que les scripts qui invoquent MySQL fonctionnent souvent à partir de la ligne de commande (en produisant des messages d’erreurs convainquants si des variables ne sont pas correctement configurées), si une requête se passe mal alors que le script est lancé par Apache, elle aura tendance à se bloquer sans nécessairement écrire quoi que ce soit dans le fichier log des erreurs. Ce problème provient souvent d’apostrophes mal placées ou de noms de champs incorrects dans la requête.
Un message d’erreur fréquent mais énigmatique que vous pouvez rencontrer dans le fichier log des erreurs est Premature end of script headers. Il indique que l’en-tête HTTP s’est mal passé, ce qui peut être dû à différentes erreurs :
- Votre script a totalement refusé de s’exécuter. Lancez-le à partir de la ligne de commande et corrigez les erreurs de syntaxe. Essayez de le rendre exécutable avec chmod +x <nom du script>.
- Votre script n’a pas les permissions de s’exécuter sous Apache.
- Les en-têtes HTTP n’ont pas été produits, ou le \n final a été oublié.
- Le script a généré une erreur avant de produire les en-têtes -- recherchez au-dessus, dans le fichier des erreurs.
Occasionnellement, ces astuces simples ne fonctionnent pas et vous devez afficher les variables pour suivre ce qui se passe. Si vous affichez vos messages d’erreur sur STDERR, ils apparaîtront dans le fichier log des erreurs. Si vous voulez les produire dans votre propre fichier, n’oubliez pas que tous les programmes exécutés par Apache le sont sous le compte de l’utilisateur inutile webuser et qu’il ne peut écrire des fichiers que dans son répertoire personnel. Vous pouvez souvent extraire des messages d’erreur utiles en faisant :
open B,">>/home/webserver/script_errors" or die "Impossible d’ouvrir : $!"; close B;
Parfois, vous devez gérer des scripts ne produisant aucune page. Lorsque WorldPay (décrit au chapitre 12) a terminé une transaction, par exemple, il peut appeler un lien vers votre site. Ce lien pointera vers un script qui écrira sûrement les détails de la transaction dans une base de données, mais il n’y a pas de navigateur pour afficher les messages de débogage : la seule possibilité consiste à les écrire dans un fichier, comme on l’a évoqué plus haut.
Si votre script est écrit en Perl, vous pouvez tirer profit du module CGI::Carp. Cependant, la plupart des autres langages utilisables pour CGI n’ont pas de mécanisme aussi pratique.
Débogueurs
Lorsque l’on programme avec un langage de haut niveau, il est généralement impossible d’utiliser directement un débogueur mais Apache permet de simuler l’environnement dans lequel il exécutera un script. La première chose à faire consiste à devenir l’utilisateur sous le compte duquel s’exécute Apache puis à se rappeler qu’Apache exécute toujours un script dans le répertoire de celui-ci et donc s’y placer. Apache passe la plupart des informations dont le script a besoin dans des variables d’environnement : déterminez ce que ces variables doivent contenir (soit en y refléchissant, soit, ce qui est plus sûr, en remplaçant votre script par un autre qui exécute env, comme on l’a vu plus haut) et écrivez un petit script qui les initialise puis lance votre CGI (éventuellement sous un débogueur). Bien qu’Apache initialise un très grand nombre de variables d’environnement, il faut savoir que la plupart des scripts CGI n’en utilisent qu’un nombre relativement réduit -- habituellement, uniquement QUERY_STRING (ou, plus rarement, PATH_INFO ). Bien sûr, si vous avez écrit le script et toutes ses bibliothèques, vous savez ce qui est utilisé, mais ce n’est pas toujours le cas. Pour donner un exemple concret, supposons que nous voulions déboguer le script mycgi, écrit en C. Allons dans .cgi-bin et écrivons un script nommé debug.cgi, qui ressemble à celui-ci :
#!/bin/sh
QUERY_STRING='2315_order=20&2316_order=10&card_type=Amex'
export QUERY_STRING
gdb mycgi
Pour le lancer, on exécutera les commandes suivantes :
chmod +x debug.cgi
./debug.cgi
Lorsque gdb apparaîtra, nous presserons r<CR>, et le script s’exécutera.
Deux choses peuvent vous faire trébucher. Premiérement si le script attend la méthode POST -- c’est-à-dire, si REQUEST_METHOD vaut POST -- alors (s’il fonctionne correctement) il attend que QUERY_STRING lui soit fournie sur son entrée standard et non dans l’environnement. La plupart des scripts utilisent une bibliothèque pour traiter la chaîne de requête : la solution simple consiste à ne pas configurer REQUEST_METHOD pour le débogage, ou de la fixer à GET. Si vous devez vraiment utiliser POST, le script précédent devrait alors être :
#!/bin/sh
REQUEST_METHOD=POST
export REQUEST_METHOD
mycgi << EOF 2
315_order=20&2316_order=10&card_type=Amex
EOF
Vous remarquerez que, cette fois ci, nous ne lançons pas le débogueur pour la simple raison qu’il attend aussi ses entrées sur l’entrée standard. Pour contourner ce problème, placez la chaîne de requête dans un fichier quelconque et indiquez au débogueur de l’utiliser comme entrée standard (dans le cas de gdb, cela implique de taper r < fichier ).
Le deuxième problème apparaît lorsque vous utilisez Perl et le module standard CGI.pm. Dans ce cas, le module détecte que vous ne l’exécutez pas sous Apache et vous demande d’entrer la chaîne de requête sous la forme de paires noms/valeurs séparées par des retours à la ligne au lieu des esperluètes habituelles. La solution simple à ce problème est très similaire à celle que nous venons de voir pour POST, mais en remplaçant les esperluètes par des retours à la ligne.
Sécurité
La sécurité devrait être le premier et le dernier souci des webmestres consciencieux. La liste de questions suivante, que vous devez vous poser, provient de Sysadmin: The Journal for Unix System Administrators, disponible à partir de la page http://www.samag.com/current/feature.shtml. Consultez également les chapitres 11 et 12.
Est-ce que toutes les entrées ont été traitées pour s’assurer qu’elles ne pousseront pas le script CGI à faire quelque chose d’inattendu ? Est-ce que le script CGI a éliminé les méta-caractères du shell non protégés si les données sont destinées à un sous-shell ? Est-ce que toutes les données provenant d’un formulaire ont été vérifiées pour s’assurer que ce sont toutes des valeurs autorisées ? Est-ce que les entrées texte ont été examinées pour rechercher d’éventuels marqueurs HTML malicieux ?
Le script CGI lance-t-il des sous-shells ? Si c’est le cas, pourquoi ? Peut-on obtenir le même résultat sans lancer de sous-shell ?
Le script CGI utilise-t-il des variables d’environnement potentiellement peu sûres, comme PATH ?
Si le script CGI est écrit en C ou dans un autre langage ne disposant pas d’un type chaîne et d’une gestion des tableaux sûrs, est-il possible qu’une entrée puisse forcer ce script à écrire après la fin d’un tampon ou d’un tableau ?
Si le script CGI est écrit en Perl, est-ce que le mode taint a été activé ?
Est-ce que le script CGI est SUID ou SGID ? Si c’est le cas, est-ce bien nécessaire ? S’il s’exécute sous le compte du super-utilisateur, a-t-il vraiment besoin d’autant de privilèges ? Ne pourrait-on pas le lancer sous un compte moins privilégié ? Le script abandonne-t-il ses super-privilèges lorsqu’il n’en a plus besoin ?
Y a t-il des programmes ou des fichiers dans les répertoires CGI qui n’ont pas besoin de s’y trouver, ou qui ne devraient pas s’y trouver, comme des shells ou des interpréteurs ?
Perl peut vous aider. Pour ce faire, placez ces lignes au début de vos scripts :
#! /usr/local/bin/perl -w -T
use strict;
....
L’option -w demande à Perl d’afficher les différents messages d’avertissement lorsque le script s’exécute. -T active le mode taint, qui empêche les sales types de vous envoyer un programme malicieux déguisé en données. La ligne use strict vérifie que toutes vos variables ont bien été déclarées.
Concernant les questions de sécurité en général, nous vous conseillons de lire la fameuse « Secure CGI FAQ » de Lincoln Stein, http://www-genome.wi.mit.edu/WWW/faqs/www-security-faq.html.