Depuis quelques semaines certaines personnes ont fait très justement remarqué dans certains posts que le niveau de certaines applications utilisant Ajax pouvait laisser à désirer au point de vue sécurité. Malheureusement ce phénomène n’est pas réservé à Ajax et touche beaucoup d’applications web qui sont peu ou mal sécurisés.
Nous allons donc essayer de faire le tour des différentes failles possibles et leurs réponses.
Dans la première partie nous tenterons d’expliquer les bases d’une sécurité adéquate, en reprenant la base et certains aspects fonctionnels.
Dans la deuxième partie (qui devrait arriver d’un jour à l’autre) nous nous intéresserons plus à des cas d’écoles et à leurs solutions.
Les risques
Les risques qu’encourent une applications sont de deux types, que nous apellerons attaques belliqueuses et attaques malicieuses.
Les attaques belliqueuses sont des attaques qui tentent de prendre le contrôle ou des informations en s’attaquant directement à l’infrastructure du serveur. Ces attaques sont liés à des éventuels problèmes de sécurité de la plateforme et ne concernent en rien la programmation de l’application et nous laisserons donc nos amis les administrateurs réseaux et autres personnes de l’exploitation s’arranger avec ces attaques belliqueuses.
Les attaques malicieuses sont plus difficiles à cerner, en général elles utilisent un faille dans la programmation de l’application web pour récupérer des informations auxquelles l’utilisateur n’a pas l’accès, effectuer des créations, modifications, suppressions, etc…
Ce sont ces attaques qui sont sous la responsabilité directe du programmeur de base, qui doit s’assurrer à tout moment que les informations qu’il délivre ou les actions qu’il autorise sont bien destinées au bon utilisateur et que ces instructions ne peuvent pas être utilisés par un petit malin dans un fjord norvégien ou en plein coeur de Paris.
Quelques principes de base
Nous allons rapeller quelques principes de base, aussi bien fontionnels que techniques qui sont à suivre en toutes circonstances pour garantir un niveau minimum de sécurité à votre application web (je sais certaines recommandations paraissent idiotes, mais vous n’avez pas idée du nombre de fois où elle ne sont pas respectées).
1. ne JAMAIS mettre un mot de passe en clair dans une page (mais alors vraiment JAMAIS, vous rigolez, je le vois, mais je l’ai déjà vu… alors ne rigolez pas trop)
2. les mots de passes stockés en base doivent être hachés (ou alors cryptés, mais le mieux reste hachés)
3. les données ultra sensibles (types numéro de carte bleu, etc…) ne doivent jamais être stockés nulle part (c’est le meilleur moyen de ne jamais se les faire voler)
4. personne, pas même l’administrateur du service ne doit avoir un accès aux mot de passes et données sensibles (comme cela aucun usurpateur ne peut tomber sur ces informations…) si le client pert son mot de passe, on lui en regénère un et on lui envoi par email…
5. Si vous ne voulez pas que quelqu’un “pique” certaines informations, ne les mettez pas en ligne (je sais c’est con de dire ça, mais c’est encore la meilleure sécurité qui existe aujourd’hui)
C’est votre devoir de développeur d’avertir votre chef de projet ou votre responsable des dangers des attaques malicieuses sur votre service et donc d’imposer ces quelques règles de base simples… Si ces règles ne sont pas respectées, le reste ne reste à rien ou en tout cas pas à grand chose.
Les requêtes
Pour certains ces notions semblent couler de source, mais 90% des développeurs ne comprennent que de façon superficielle certains concepts essentiels et fondateurs du web d’aujourd’hui…
Ces notions sont très importantes, puisque c’est sur ces bases que se fonderont les attaques malicieuses et donc aussi votre technique de défense (ton kung fu très bon…)
Les échanges sur le web se basent sur le protocole HTTP.
Ce protocole est assez simple à appréhender.
Vous voulez aller jeter un oeil sur une page web, en l’occurence http://www.babozor.com/index.php
Pour faire ceci, votre navigateur va envoyer un requête au serveur qui héberge ce site web et lui demander de bien vouloir lui renvoyer la page demandée.
Cette action est donc un requêtes du client vers le serveur.
Le serveur peut répondre de divers manières, si la page est valde et que vous y avez accès, il vous renvoi le contenu de la page qui est interpréte par votre navigateur et affiché par celui ci. Si il y a un problème, le serveur renvoi un code (par exemple la fameuse 404 pour une page inconnue, etc…) qu vous renseigne sur le problème survenu.
Traditionnellement il y a 2 façons d’envoyer des requêtes vers un serveur:
- GET: vous envoyez votre requête sous la forme d’un chaine de caractère qui comprend l’url de la page et toutes les variables (par exemple http://www.babozor.com?leplusfort=babozor)
- POST: vous envoyez votre requête au serveur sous la form d’une url et d’un chaine de caractère rajouté au header de la requête qui content les variables.
Quelle différence? pour le serveur aucune ou presque, à part de rendre explicite les variables en GET dans le navigateur (le client voit les variables dans la barre d’adresse de son navigateur).
Client / Serveur
Cette notion là encore est une notion fondatrice que peu de développeur maitrisent vraiment.
Les attaques malicieuses ne viennent jamais du serveur (sinon ce sont des attaques malicieuses, et ne vous concernent plus), mais du client.
Aucune action ne peut être effectuée sur le serveur si on ne les autorise pas. Pourquoi?
Que vous utilisiez ou non un langage dynamique (j’espère, sinon ce post vous n’est d’aucune utilité), la page affichée à l’utilisateur est une page statique, générée par Apache avec l’aide de PHP… PHP ou tout autre langage web n’est qu’une sous couche du serveur web, qui aide celui ci à construire ses pages. Les pages délivrées à l’utilisateurs sont toujours statiques, il ne peut en aucun cas les modifier… c’est vous qui modifiez les pages, le client ne peut que les visualiser.
C’est un concept important à saisir.
Il est donc important de saisir la relation embivalente Client / Serveur.
Le client envoi des requêtes et reçoit des réponses, le serveur traite ces requêtes et lui renvoi des pages.
Certains contrôles basiques peuvent être effectués côté client (tel que validation d’un formulaire, par exemple), mais ces contrôles restent limités. Par exemple, on ne vérifie pas le mot de passe côté Client, puisque ça voudrait dire envoyer “en clair” le mot de passe au navigateur pour que celui ci vérifie sa validité. Un contrôle mot de passe doit toujours rester côté serveur.
Les contrôles côté client doit être limités à la comodité pour l’utilisateur…
Cette notion est d’autant plus importante à maîtriser, si vous vous lancer dans le codage d’une application Ajax, où la délimitation entre Seveur / Client devient plus floue… ce passage n’est pas nécessairement associé à une page, mais à un requête et à une réponse du serveur.
Bon je crois qu’on en a assez fait pour maintenant. Pour certains cela a du rafraichir quelques souvenirs et pour d’autres leur causer un gros mal de crâne.
Demain on s’attaque aux choses sérieuses, les attaques malicieuses et la protection contre des actions non autorisées.