Sécuriser un site Web

C'est une question récurrente sur tous les forums spécialisés et j'ai, moi aussi, dû me pencher sur la question. Ce tutoriel a donc pour but d'être une sorte de guide afin de vous aider à comprendre ce qu'est la sécurisation d'un site Internet, de vous guider dans vos choix et enfin, de les mettre en oeuvre.

Le filtrage des données

Certaines données sont échangées lors de l'accès à une page. Notamment lors de l'envoi de formulaires. Si elles ne sont pas filtrées, ces données peuvent s'avérer dangereuses.

Les risques

Les risques sont simples. Si vous ne filtrez pas correctement les données que vos visiteurs vous transmettent, alors, vous laissez une porte ouverte à l'exécution de codes malicieux. Nous nous attacherons plus particulièrement au développement PHP/MySQL.

Dans ce cas, les risques sont principalement de quatre types :

Les inclusions PHP

Une spécificité de PHP est la possibilité d'inclure dynamiquement un script. Lorsque cette inclusion est basée sur une variable que l'utilisateur fourni, il faut veiller à ce qu'il ne puisse pas modifier le chemin de l'inclusion.

Dans le cas contraire, un individu malintentionné pourrait inclure un script se trouvant sur un serveur distant et ainsi exécuter du code malveillant.

Les injections SQL

Imaginons la lecture d'un article dans une table. Pour le sélectionner, on utilisera :
SELECT * FROM article WHERE id='(variable id)'
Maintenant, imaginons que (variable id) soit égal à 4'; DELETE FROM article WHERE id!='0 et qu'il ne soit pas du tout filtré. Voici ce qu'il pourrait arriver :
SELECT * FROM article WHERE id='4'; DELETE FROM article WHERE id!='0'

On voit que cette méthode est très puissante puisqu'en utilisant des noms génériques, on pourrait supprimer de nombreuses tables.

On peut aussi prendre l'exemple d'une authentification :
SELECT * FROM membre WHERE login='(variable login)' AND password='(variable pass)'
Pour un identifiant existant, on pourrait passer ce test grâce à une simple injection :
SELECT * FROM membre WHERE login='mon_identifiant' AND password='x' OR login='mon_identifiant'

Pour résoudre ces problèmes, il faut être particulièrement attentif à ce que les données de l'utilisateur ne contiennent pas d'apostrophe ou de guillemets. Mais pas seulement !

Il faut aussi vous assurer de toujours encapsuler les données susceptibles d'émaner de l'utilisateur avec des apostrophes ou des guillemets dans les clauses SQL.

Note relative à PHP :
En PHP, il existe une façon native d'éviter les injections SQL. Il s'agit de la variable de configuration magic_quotes_gpc du fichier php.ini. Je ne vous recommande pas son utilisation pour une raison simple : tous les serveurs ne sont pas configurés de la même façon. Ainsi, votre script peut devenir vulnérable sur d'autres machines.

Les injections HTML/Javascript

Cette pratique plus connue sous le nom de Cross Site Scripting (XSS) consiste à afficher sur votre site, par tout moyen, du code HTML/Javascript. Cela peut être une redirection Javascript dans un message au sein d'un forum ou pire, la récupération de la variable de session.

Les attaques XSRF

Encore plus vicieuses, ces attaques exploitent la connexion d'un administrateur connecté au site pour lui faire faire des actions sur ce dernier (suppression de contenu, la plupart du temps).

Le principe est simple, la personne connectée au site est invitée à se rendre sur une page web dans laquelle une image contient le lien direct permettant de supprimer du contenu sur le site. Comme cette dernière envoi son identifiant de session à cause du cookie placé à la connexion, le contenu est supprimé sans souci.

Si il s'agit d'un forum open-source, vous n'aurez aucune difficulté pour connaître cette fameuse URL. C'est pourquoi, il faut demander confirmation grâce à une seconde requête HTTP (bien-sûr, la page précédente aura délivré un "ticket" attestant de son passage sur cette dernière). De plus, il faut privilégier la méthode POST pour les modifications car l'affichage d'une image dans une page HTML ne peut pas la simuler.

Sécurisation des données

Pour éviter ce genre de scénario catastrophe, une seule solution, le filtrage des données. Voici deux filtres courants qui annihilent la plupart des risques :

Filtre mot

Il permet de filtrer tout ce qui n'est pas un mot. Par mot, on entend une série de caractères alphanumériques. Voici un exemple en PHP :

function get_word($name)
 {
 if($_REQUEST[$name]==eregi_replace('[^a-z0-9_]', '', $_REQUEST[$name])
return $_REQUEST[$name];
 else
return false;
 }

Les données ainsi récupérées sont inoffensives pour presque toutes les vulnérabilités. Je le recommande particulièrement pour les inclusions PHP et le filtrage des identifiants et mots de passe.

Filtre texte

Parfois, on doit permettre à l'utilisateur de saisir un contenu plus fourni que de simples mots. Ainsi, il faut penser à filtrer les caractères sensibles comme :

  • les apostrophes ou guillemets pour les injections SQL.
  • les signes < et > pour les injections HTML/JS ou, si vous autorisez HTML, la balise script et les attributs d'évènement tels que onclick, onmouseover etc...

Les XBBCodes pallient simplement à ce problème de filtrage.

Précaution SQL

Lorsque vous ajoutez du contenu venant de l'utilisateur dans une table, veillez à utiliser les guillemets pour l'entourer, dans le cas contraire, un mot avec espaces serait capable de faire des injections SQL.

L'authentification

Aujourd'hui, la majeure partie des sites Internet sur le web sont dynamiques. Cela signifie que le site peut être modifié en ligne par les utilisateurs. Il faut donc mettre en place un espace permettant de se connecter et d'administrer le site. Voici une aide concernant les mesures de sécurité à prendre.

Ce qu'il faut savoir

Lorsque vous accédez à une page, des données sont échangées entre votre navigateur, appelé client, et le site Internet, sur le serveur. C'est bien connu. Cependant, ces informations ne sont pas transmises directement et transitent par un certain nombre de relais avant d'arriver à destination.

Dans la plupart des cas, ce n'est pas important puisque la majeure partie des échanges entre un site Internet et un client sont publics. Cependant, certaines données dîtes sensibles doivent subir un traitement particulier. En effet, de nombreux sites Internet proposent un formulaire de connexion pour accéder à un espace personnel.

Une fois votre mot de passe vérifié, une session est ouverte. Cette session a, en général, une durée de vie limitée à un certain temps d'inactivité. Afin de vous reconnaitre en tant que possesseur de la session ainsi ouverte, le site Internet vous attribue une clé (souvent, une chaîne de 20 caractères) conservée dans un cookie (sorte de fichier temporaire de stockage).

Ainsi, à chaque fois que vous demandez une information au serveur, vous lui envoyez cette clé d'authentification provisoire.

Les failles

Etant donné la complexité apparente de cette méthode, on serait en droit de supposer que ce système est tout à fait sûr et qu'il n'y a pas de risque réel de piratage. Mais il n'en est rien. En effet, comme cela a été souligné plus haut, jusqu'ici, tous les échanges ont été fait en clair. Et deux informations sensibles ont pu être observées par une entité tierce :

La variable de session

Elle sert à vous authentifier auprès du serveur. Si celle-ci est possédée par quelqu'un d'autre, alors, il héritera de vos droits. Cela peut se traduire par la suppression de données ou par du spam (envoi massif de messages, souvent publicitaires).

Les informations d'identification

En récupérant votre mot de passe et votre identifiant, le pirate aura libre champ et sera en mesure d'exploiter votre compte à plusieurs reprises (par de nouvelles connexions). Il pourra de plus changer votre mot de passe et ainsi vous priver d'accès (sur un site mal codé, la variable de session suffit, il faut absolument redemander le mot de passe pour pouvoir changer ce dernier).

Certes, ces informations sont noyées dans une masse importante de données dîtes publiques, mais il est aisé d'appliquer des filtres sur celles-ci. Par exemple, pour la variable de session, nous pouvons procéder par élimination en partant du principe qu'elle est souvent stockée dans un cookie et qu'il s'agit d'une chaîne de plus de 15 caractères et de moins de 128 caractères. Pour le mot de passe, c'est encore plus simple. Il est souvent transmis par la méthode HTTP Post et le nom du paramètre est souvent explicite (recherche de 'password' ou 'pass'). Ou encore, il suffit de détecter un cryptage MD5, mais nous verrons cela un peu plus bas.

Les différentes mesures à prendre

Cette situation, encore souvent rencontrée, peut avoir des conséquences catastrophiques selon les droits accordés aux utilisateurs. Pour éviter ce phénomène, il existe quatre voies principales :

  1. Le captcha
  2. La sécurisation SSL
  3. Le cryptage MD5
  4. Optimisation des sessions
Le captcha

Imaginons l'envoi des milliers de combinaisons de mots de passe possibles au serveur avec un identifiant connu. Il arrivera forcément un moment ou le mot de passe sera découvert. Il faut donc s'assurer que l'entité qui tente de se connecter est bien un humain.

Le captcha intervient donc. Pour la petite histoire, captcha est un acronyme en anglais qui signifie Test public de Turing complètement automatique ayant pour but de différencier les humains des ordinateurs.

Les deux captchas à utiliser sont le captcha visuel qui est une image contenant un code (brouillé pour ne pas être lisible pas un ordinateur avec un OCR) et le captcha vocal qui transforme le code en un son brouillé pour éviter qu'un logiciel de reconnaissance vocale soit en mesure de le décoder. L'alternative vocale permet de conserver l'accès aux personnes victimes d'un handicap visuel.

Pour un exemple de ce type de protection, voici notre formulaire de connexion à nos sites.

A savoir : si vous ne prévoyez pas ce type de protection, l'erreur à ne surtout pas faire, c'est de donner du feedback sur l'existence (ou non) de l'utilisateur. Restez évasif en produisant la même erreur pour le nom d'utilisateur et le mot de passe.

La sécurisation SSL

C'est l'arme ultime actuelle contre la récupération des informations sensibles. L'utilisation du SSL pour les transferts entre client/serveur se traduit par un cryptage total de toutes les données transmises. Cependant, sa mise en place demande quelques petites adaptations.

La sécurisation SSL est inefficace si il existe un moyen de la contourner. C'est pourquoi, vous devez vous assurer que vos utilisateurs utilisent bien l'adresse sécurisée (commençant par https et non http). Deux voies peuvent être empruntées :

La redirection HTTP
En utilisant un fichier .htaacces vous pouvez forcer la connexion en SSL. Voici ce que j'utilise pour sécuriser l'espace de statistiques Webalizer de mes sites :
RewriteEngine on
# HTTPS for stats
RewriteCond %{HTTPS} !=on
RewriteRule ^stats(.*) https://bbcomposer.elitwork.com/stats$1 [R=301,L]
La redirection au sein de vos scripts
Il arrive que l'on utilise le même domaine/dossier en HTTP et HTTPS. Dans ce cas, c'est au niveau de vos script qu'il faudra faire cette redirection. En PHP, voici la solution :
if($_SERVER['SERVER_PORT'] != 443)
{
header('Location: https://elitwork.com/admin.php');
exit;
}

Attention cependant aux inconvénients du SSL. Comme tout système de cryptage, le SSL utilise beaucoup de ressources notamment en mémoire et utilisation du processeur. C'est pourquoi je vous conseille son utilisation lorsque les droits de l'utilisateur sont extrêmement sensibles (suppression de base de donnée, modification des pages du site sans validation etc...).

De plus, pour le confort de vos utilisateurs, vous devrez passer par un organisme de certification afin de valider votre certificat de sécurité (environ 180 à 200€).

Le cryptage MD5

Cette technique est souvent utilisée à cause du manque de support du SSL avec certains hébergements gratuits ou mutualisés ou encore pour des données moins sensibles. Le principe consiste donc à crypter une partie seulement des informations échangées. En l'occurrence, le mot de passe. Mais attention à ne pas tomber dans le piège classique !

En effet, certains programmeur procèdent comme suit :

L'utilisateur entre son mot de passe, et soumet le formulaire. Le mot de passe est crypté en Javascript. Le champ de mot de passe est vidé et le mot de passe crypté est inséré dans un champ caché.

Enfin, le formulaire est soumis au serveur. Le serveur récupère le mot de passe crypté et le compare aux mots de passe cryptés dans la base.

Cela ne sert strictement à rien ! En effet, le pirate n'aura qu'à envoyer directement la chaîne cryptée ! A la limite, ça permet au pirate de ne pas utiliser le mot passe sur des sites différents et à l'administrateur de la base de donnée de ne pas voir les mots de passe en clair.

Pour qu'un cryptage MD5 soit efficace, il faut inclure un paramètre variable au cryptage. Cela peut-être la date du jour, mais il existe un risque en cas de différence de réglage (à moins d'une synchronisation, mais le risque sera de toute façon toujours présent).

Comme paramètre variable, je propose le captcha. En effet, ce captcha est non seulement variable, mais de plus, difficilement déductible par le robot à partir de l'image et/ou de son alternative vocale.

L'idée est donc la suivante :

  • L'utilisateur saisi l'identifiant, le mot de passe et le captcha et soumet le formulaire.
  • Un traitement en Javascript récupère le mot de passe et le captcha, les réunis en une seule chaîne et vide leurs champs de saisie respectifs. La chaîne obtenue est cryptée et insérée dans un champ caché. Enfin, le formulaire est soumis.
  • Côté serveur, la chaîne est récupérée. Le mot de passe correspondant à l'utilisateur donné est récupéré dans la base de donnée et combiné au captcha. Le tout est crypté en MD5. Et la chaîne obtenue est comparée à celle reçue. Si le test d'égalité est concluant, une session est ouverte.

De cette façon, le pirate qui réussira a obtenir la chaîne devra aussi récupérer le captcha qui lui est associé ce qui lui complique fortement la tâche.

Note

Il y a fort à parier que MD5 sera progressivement remplacé par SHA-1 ou SHA-256 qui, bien que basés sur le même principe, sont plus sûr que MD5. Les algorithmes de transformation en Javascript pour ces trois types de hachage de données peuvent être trouvés ici. En PHP, les fonctions MD5() et SHA1() ont été implémentées depuis respectivement PHP 4 et PHP 4.3.0.

Pour démontrer la vulnérabilité du hachage MD5, voici un petit algorithme Javascript permettant de cracker une chaîne hachée en MD5. Ce n'est pas le plus élégant, car il ne fait que comparer toutes les combinaisons possibles (brute force, peut prendre plusieurs heures pour une chaîne de 4 caractères...).

Pour l'utiliser :
var md5 = new md5_checker('ma_chaine_hachée'); alert(md5.word); // Affiche le mot trouvé

Optimisation des sessions

Les sessions que nous avons décrites peuvent être optimisées de façon à être plus sécurisées.

Pour trouver une variable de session, on peut, comme pour les mots de passe, essayer toutes les combinaisons possibles. Ainsi, plus la clé de session a un nombre de caractères importants et plus le nombre de caractères éligibles est grand, plus cette opération devient impossible surtout lorsque la durée de validité de la session est faible. Ce raisonnement peut être appliqué aux mots de passe lorsqu'aucun captcha n'est mis en place.

Aussi, on peut lier la session à l'IP du visiteur afin de s'assurer qu'elle ne sera pas volée (même si ce n'est pas garanti). Par contre, vous devez prendre en compte le fait que certains visiteurs changent d'IP à chaque requête. La seule solution est de faire une exception pour ces derniers (ex.: si au bout de 5 requêtes le visiteur n'a pas changé d'IP alors on considère qu'il ne changera jamais et on lie définitivement l'IP à la variable de session).

Il est également possible de mettre le nom de l'utilisateur dans les cookies. De cette façon, même si un pirate trouve une session valide, il ne pourra pas l'utiliser sans trouver le nom d'utilisateur auquel cette dernière correspond.

Enfin, la variable de session doit être passée au serveur soit avec POST, soit avec les cookies. Si celle-ci est dans l'URL, une capture d'écran malencontreuse comme les journaux Apache (les réferants y sont répertoriés) pourraient dévoiler cette variable.

Projet

J'utilise le cryptage SSL pour les sites d'Elitwork, mais le défi que représente la seconde alternative m'intéresse. Je souhaite compiler tout ça dans un petit script sympa entièrement personnalisable qui sera mis à votre disposition ici. Revenez donc faire un tour à l'occasion ;).

J'ai commencé par ajouter cette fonctionnalité à notre CMS, voici le script en question. Le script côté serveur sera mis en ligne dès que nous aurons un peu de temps.

Les chapeaux noirs

Ils sont nommés ainsi car ils sont passés du côté obscur du référencement. Pour eux, tous les coups sont permis, et plus ils sont bas, plus ils font mal. On pourrait, en quelque sorte, appeler ça le dé-référencement. Si vous ne souhaitez pas voir ruiner tous vos efforts, voici les principaux pièges à éviter :

La duplication de contenu

Le principe de la duplication de contenu est très simple. Il s'agit de prendre le contenu de votre site et de le diffuser ailleurs que sur votre site. De cette manière, votre contenu n'apparait plus comme original aux yeux des moteurs, voire, en cas d'excès, il peut être considéré comme du spam.

Malheureusement, il n'existe pas de solution définitive pour s'en prémunir. Mais la loi est avec vous. Notamment, celle relative aux droits d'auteur. Un mail au filou qui aura tenté ce subterfuge suffira dans la plupart des cas.

Le meilleur moyen de savoir si votre contenu est dupliqué, c'est de prendre une phrase complète sur une de vos pages, de la mettre entre guillemets et de faire une recherche dans un moteur.

Mais cela n'est pas garanti car, bien souvent, ils spécifient aux robots de ne pas indexer leurs pages (ou de ne pas les conserver dans le cache).

La faille des URL multiples

Une technique bien connue du référencement est la réécriture d'URL. Cela signifie que les adresses des pages d'un site sont réécrite de façon à "plaire" davantage aux moteurs.

Le problème, c'est que cela induit une faille exploitées par quelques malins. En effet, sur beaucoup de sites, on peut accéder aux pages via l'adresse réécrite, mais aussi, via la vraie adresse. Cela signifie que l'on peut accéder aux mêmes contenus avec des adresses différentes.

Ceci reproduit le phénomène de duplication de contenu et des personnes peu scrupuleuses peuvent être tentées de faire des liens vers ces adresses afin que Google assimile cela à du spam et retire vos pages de son index.

Pour éviter cela, vous pouvez agir à deux niveaux :

Le fichier robots.txt
Il permet de spécifier les URL qui ne doivent pas être indexées. Comme, par exemple, celles contenant des paramètres CGI. Vous pouvez vous inspirer de celui que nous utilisons :
User-agent: *
Disallow: /index.php*
Disallow: /?*
Disallow: /*.html?*
Les entêtes HTTP
Les langages serveur comme le PHP permettent de spécifier qu'un fichier n'existe pas grâce à une erreur 404. En PHP, cela se fait ainsi :
header('Date: ' . gmdate('D, d M Y H:i:s') . ' GMT', true, 404);

La transmission de malus

C'est simple, il s'agit d'utiliser des sites Internet que Google a récemment banni de son index pour transmettre leur mauvaise réputation à des sites concurrents.

Surveillez vos réferrants (sites qui pointent vers le votre) régulièrement. Sachez que vous avez le droit d'exiger le retrait d'un lien qui pointe vers votre site.

La casse des partenariats

Une pratique très connue sur le web est le partenariat. Un lien réciproque sensé aider les deux parties à développer leur trafic et leur popularité.

Cependant, les partenariats doivent être régulièrement surveillés. En effet, il existe plusieurs pratiques malveillantes qui peuvent vous faire perdre bêtement du trafic ou de la crédibilité.

En effet, les partenaires sont des personnes tierces que vous ne pouvez contrôler. Il arrive que des sites Internet ferment leur portes. Dans ce cas, vous risquez d'avoir des liens morts (dans le meilleur des cas) ou avoir un lien vers un site de récupération de trafic. Il s'agit de récupérer des noms de domaines abandonnés pour le trafic potentiel qu'ils peuvent apporter.

Mais il y a pire. Une pratique consiste à envoyer des e-mails à vos partenaires leur annonçant que vous souhaitez mettre fin au partenariat pour une raison ou une autre. Votre partenaire ne fera assurément pas d'enquête et retirera le lien sans se poser de question.

Le conseil, pour éviter ces situations, c'est de toujours vérifier si vos partenaires respectent les termes fixés par le partenariat à intervalles réguliers.

En conclusion

Ce que l'on peut retenir de la sécurisation d'un site web, c'est, tout d'abord, la complexité et la diversité des attaques. Mais enfin, et surtout, leur caractère évolutif, la fameuse poursuite infinie entre gendarmes et voleurs...

Derniers sites créés

Le Sauvage

Le SauvageNous avons réalisé un mini-site pour le restaurant Le Sauvage situé à Cassel. Suite

Actualité

Performance améliorée

Nous avons profité d'un changement de serveur web pour améliorer une fois encore la performance de nos hébergements. Suite

A propos

Nous avons créé l'agence Elitwork en 2006 au coeur du Nord-Pas-de-Calais dans le triangle Arras - Cambrai - Douai. Depuis, nous forgeons notre savoir-faire au jour le jour afin rester experts du web et des technologies d'Internet en général.
Spécialisés dans la créations de sites Internet et le développement d'application/progiciels web sur mesure, nous permettons à nos clients de réussir leur transition vers un système d'information connecté. En savoir plus

Actu de l'agence

Orange HTML5 Hackathon

Orange HTML5 HackathonNicolas Froidure, le développeur d'Elitwork a remporté avec son équipe le grand prix du jury du concours de hacking Orange HTML5 Hackathon. Découvrez cette folle journée ! Suite

Nous contacter

Elitwork SARL
10, rue Antoine DEQUEANT
62860 Oisy le Verger
Tél. : 03 21 59 62 24
E-mail