Principes de base

Auteur : palkeo
Créé le : le 24/10/2008 à 19:05
Visualisations : 2643
Ce tutoriel est composé des parties suivantes :

Introduction

Dans ce tutoriel, je vais vous présenter les bonnes attitudes à avoir pour bien sécuriser son site : Les failles décrites dans les tutos représentent peut-être la moitié des failles qu'on peut trouver sur les sites web, mais le reste est du à des fautes d'inattention du webmaster, ou à des oublis de validation des données.

Toujours valider les données

La première chose à faire, lorsqu'on créé un site web, et qu'on reçoit les données des utilisateurs, c'est de les valider : on va effectuer une série de vérification qui vont déterminer si les données que l'utilisateur envoie sont valides.
Pour ça, je vous conseille d'imaginer ce que votre script pourrait recevoir, et de voir comment il réagirait.
D'une manière générale :
Si vous attendez un nombre entier, vérifiez toujours que l'utilisateur en envoie bien un.
Si vous attendez une chaine de caractères, vérifiez qu'elle n'est pas vide, et qu'elle à une longueur correcte.
Si vous attendez le choix d'une liste déroulante, vérifiez toujours que l'utilisateur n'envoie pas autre chose...

Mais ce ne sont pas les seules choses à vérifier :
Admettons que votre script attende l'ID d'un article, pour voter pour cet article.
Vous devez toujours vérifier que cet article existe ! Et c'est valable pour tout ce qui a un ID.
Et pensez toujours à regarder que l'ID est un nombre, avant de vérifier qu'il existe. Sinon, vous êtes bon pour une injection SQL... :/

Si une vérification échoue, affichez simplement un message d'erreur, et pensez bien à arrêter votre script !
Pour cela, il existe la fonction exit(). Par exemple, pour vérifier qu'une chaine de caractères n'est pas vide :
Code : PHP
if(empty($_POST['message']))
 exit('Erreur : le message est vide !');

C'est à ce manque de validation que l'on doit la faille upload, la faille include, ou encore l'injection SQL.

Et validez aussi bien les $_GET, $_POST que $_COOKIE !

A-t-on les droits ?

Si votre site a un espace membre, cette partie vous concerne ! Et si vous avez plusieurs groupes (par exemple, administrateur, modérateur, et membre), vous êtes encore plus concernés !

Pensez à toujours vérifier qu'un membre à les droits pour effectuer une action !
Par exemple, si il est possible aux membre de se supprimer leur compte, et que votre script de suppression prend pour paramètre l'ID (ou le pseudo) du membre à supprimer, vérifiez que le membre à supprimer est bien celui qui demande la suppression, sinon, n'importe qui pourrait supprimer n'importe quel compte.

Si votre site comporte un forum, vérifiez bien que le membre est connecté avant d'afficher un lien pour poster un message (il s'agit pas que quelqu'un qui n'est pas inscrit puisse poster). Et ce n'est pas tout !
Faites la même vérification avant d'afficher le formulaire qui permet de répondre, et refaites là avant d'insérer un message dans la base de données.
Sinon, quelqu'un qui connait le fonctionnement du site pourrait poster des messages sans passer forcément pas les liens pour répondre, ni par le formulaire, mais directement en envoyant les données au script qui va se charger d'ajouter le message dans la base de données du site.

Bref, vous devez systématiquement vérifier que l'utilisateur a le droit d'effectuer une action !

Ne faites pas confiance à l'utilisateur

Autre point important : L'utilisateur peut tout faire, et tout modifier !

Une fois, j'ai été sur un site qui, pour se souvenir de nous, conservait notre ID de membre dans un cookie. Et le webmaster faisait une confiance aveugle aux cookies. Sans se rendre compte qu'ils étaient falsifiables.
Résultat : Il m'a suffit de changer l'ID contenu dans le cookie pour me connecter sur le compte du webmaster, et pouvoir administrer le site :/
Pour cet exemple, il fallait stocker l'ID du membre, mais également le mot de passe, afin d'éviter ce genre de problèmes (bien entendu, on ne stocke pas le mot de passe en clair, mais on utilise une fonction de hachage pour conserver seulement une "empreinte" de ce dernier).

Ou encore, j'ai vu un site qui avait une fonction pour changer le mot de passe en cas d'oubli : On cliquait sur un lien envoyé par mail. Ce lien avait un paramètre : l'ID du compte dont on souhaitait remettre un mot de passe.
Résultat : Il suffisait de mettre l'ID d'un autre membre, ça changeait son mot de passe, nous le donnait, puis on n'avait plus qu'à se connecter à son compte...
Il aurait bien entendu fallu utiliser un jeton généré au hasard, qui aurait aussi été envoyé au script.

Pour vous prémunir ce ce genre de problèmes, mettez vous dans la peau d'un hacker, et chercher comment il serait possible de faire pour contourner votre script, ou effectuer des actions imprévues. Regardez chaque variable et imaginez toutes les valeurs inattendues qu'elles pourraient prendre.
Et n'hésitez pas à y passer du temps, à relire votre script, à imaginer le parcours de données inattendues, et leurs conséquences... C'est un point très important !

Récapitulatif des failles

Les injections SQL
Quand vous écrivez chaque requête SQL, pour chaque variable que vous incluez à la requête, regardez son type :
Si c'est une chaine de caractère, utilisez la fonction mysql_real_escape_string() pour "échapper" la chaine, et vous prémunir des injections SQL. N'oubliez pas d'entourer le paramètres de guillemets dans votre requête ;)
Si votre paramètre est un nombre entier, pas besoin de guillemets : c'est un nombre. pensez simplement à vérifier que c'est bel et bien un nombre, ou utilisez la fonction intval().

La faille XSS
Avant d'afficher une chaine de caractère entrée par un utilisateur (un message, ou même un pseudo !), utilisez toujours la fonction htmlspecialchars() qui va rendre d'éventuelles balises HTML inoffensives.

Les attaques CSRF
Pour vous prémunir contre ce genre d'attaques, vous devez simplement utiliser des jetons pour toutes les actions importantes à effectuer (pour toutes les opérations d'administration, la modification du profil...).
Pour le changement de mot de passe, le mieux reste de demander l'ancien mot de passe, puis le nouveau.

Conclusion

Avec tout ça, vous devriez avoir toutes les informations nécessaires pour sécuriser votre site web :)
Mais, restez toujours vigilant pendant que vous codez !

Pour finir, apprenez cette phrase par cœur, collez là en dessous de votre écran, et ayez-là toujours en tête :
Citation :
Never trust user input
En français : Ne jamais faire confiance à l'utilisateur.