Sécurité des applications AJAX

Date : 01 Octobre 2007

Introduction

AJAX n'est pas une technologie, mais une architecture client/serveur qui consiste à découper une application web de la façon suivante :

  • une présentation des données en utilisant les standards XHTML et CSS,
  • la manipulation dynamique des pages à travers le modèle DOM,
  • la manipulation des données via le format XML et les feuilles de style XSLT,
  • l'échange des données de manière asynchrone avec l'objet "XMLHttpRequest",
  • le tout étant assemblé avec du JavaScript.

Une architecture AJAX hérite donc des risques sécurité pesant sur ces technologies depuis quelques temps déjà.

De ce fait, plutôt que de parler de nouvelles vulnérabilités, on parlera plutôt de vulnérabilités liées à une nouvelle utilisation de ces technologies sous-jacentes. Cette architecture est très prisée actuellement car elle offre des possibilités de traitement dynamique des pages HTML, et s’inscrit dans la mouvance du web 2.0.

Nous vous présentons ci-dessous les points "critiques" en termes de sécurité d'une application AJAX.


L'objet "XMLHttpRequest" et le langage JavaScript

Cet objet permet de faire des requêtes HTTP afin de récupérer des données au format XML qui pourront être intégrées à une page HTML.
Il a été initialement introduit et soutenu par Microsoft, en vue d'étendre les fonctionnalités offertes à son navigateur. Il n'est par conséquent pas normalisé.
Du coup, le fonctionnement diffère en fonction des différents navigateurs du marché :

  • pour les navigateurs Microsoft Internet Explorer 5 et 6, AJAX nécessite l'activation des ActiveX sur les clients,
  • pour les autres navigateurs (y compris Internet Explorer 7), AJAX nécessite l'activation de JavaScript.

Les vulnérabilités induites par ces deux approches sont donc naturellement reconduites sous AJAX.
Cet article ne traite que de JavaScript, mais les points abordés doivent être facilement transposés à l’utilisation des ActiveX.

Prenons l’exemple d’un formulaire HTML de saisie des données d’un véhicule automobile. En HTML "classique", le serveur peut :

  • Soit envoyer la totalité des marques, modèles par marque, variantes par modèle… Cette solution entraîne un volume d’envoi d’informations important.
  • Soit proposer un formulaire dynamique (contenant en fait du code JavaScript), qui demande d’abord la marque du véhicule, puis en fonction du choix de l’utilisateur, fait une requête au serveur qui va renvoyer une deuxième page avec le choix de l’utilisateur et les informations qui permettront la sélection du modèle (seulement les modèles de la marque). Cette solution économise le volume d’informations échangé, mais devient beaucoup moins ergonomique pour l’utilisateur : échanges HTTP entraînant des réaffichages de page, manque de souplesse (il est impossible de consulter la liste des modèles sans avoir rempli la liste des marques), …

Avec AJAX, la solution va pouvoir être plus souple et transparente pour l’utilisateur, et plus performante du point de vue du volume de données transférées : le choix de la marque va entraîner un échange transparent avec le serveur qui va renvoyer seulement les informations suivantes nécessaires (dans un format brut réduit aux seules informations utiles, sans mise en forme HTML), et la page va se remplir progressivement sans pour autant se recharger totalement.

Tout ceci est réalisé au moyen d'un code JavaScript contenu dans la page HTML présentée, en utilisant un (ou plusieurs) objet(s) "XMLHttpRequest" afin de dialoguer avec l’application coté serveur.

Ce mode de fonctionnement est un des premiers problèmes potentiels de sécurité : l'utilisateur final n'a pas la visibilité sur l'ensemble des informations échangées avec le serveur. Il n’a même pas conscience des opérations sous-jacentes, qui se font du coup à son insu.
Un formulaire malicieux peut alors effectuer des traitements et véhiculer des informations sensibles de manière tout à fait transparente.
Les risques sécurité induits par l’utilisation du JavaScript sont donc aggravés avec cette architecture.
Il n'y a d'ailleurs pas moyen de bloquer ce type de transfert par l'intermédiaire d'un pare-feu car il s’inscrit dans un flux HTTP habituellement autorisé.

 

Les contrôles coté client

Le langage JavaScript permet la manipulation d'informations sur le poste client. Utilisé dans un flux HTTP classique, il peut manipuler les informations chargées dans une page HTML. Ces manipulations peuvent être effectuées dans le but d'améliorer l'affichage, de rendre une page plus vivante, ou pour effectuer des traitements "invisibles".

Ce langage est souvent utilisé pour effectuer des contrôles des données entrées par l'utilisateur directement du côté client, en vue de ne pas envoyer inutilement vers le serveur des données trialement erronées (par exemple, contrôle du format d’une adresse IP). Cette architecture offre la possibilité de réaliser des applications plus complexes coté client (notion de "rich client").

Il y a donc fort à parier que beaucoup de développeurs vont naturellement tomber dans le travers d'effectuer aussi des contrôles de sécurité coté client. Ceci est une mauvaise pratique : les contrôles sécurité d’une application web doivent toujours être effectués du coté serveur (seul endroit pouvant être considéré comme "sûr", car "sous contrôle", à la différence du poste client, qui lui peut se trouver n'importe où et est donc "hors contôle").

Ce point est donc à surveiller car l'effet pervers de ce type de développement est que l'utilisateur croit avoir affaire à une application bien protégée, alors qu’en fait la sécurité de son application centrale est affaiblie. Un attaquant peut en effet contourner les contrôles de sécurité en désactivant l'interprétation du langage JavaScript, ou en forgeant une requête HTTP valide avec des informations erronées (et potentiellement dangereuses).

 

Les environnements ("frameworks") AJAX

L'architecture AJAX offre aussi la possibilité de générer des relais ("proxies") JavaScript qui permettent à un code JavaScript coté client d'appeler directement des services web ("web services") proposés par le serveur. En général, sur une application basée sur les "web services" (application "n-tiers"), une couche de sécurité est développée coté serveur pour contrôler les accès aux "web services".
Avec AJAX, il semble cependant possible d'appeler directement ces "web services" depuis le client, sans passer par la couche sécurité...


L'injection de code SQL

Des applications serveur sont aussi réalisées à base de solutions PHP/MySQL. Ce type de solution utilisant une base de données coté serveur doit alors bien tenir compte des risques d'injection SQL.

 

Le "Cross Site Scripting"

Comme toutes les applications web, une application AJAX peut être vulnérable uax attaques de de type "Cross Site Scripting". Par contre, les conséquences d'une telle vulnérabilité est ici aggravée.

En fait, au cours des échanges AJAX propres (ceux qui sont effectués entre deux requêtes HTTP standards), le serveur a la possibilité d'envoyer des morceaux de code JavaScript. Le client peut alors exécuter ce code grâce à la fonction JavaScript  "eval()".
Il s'agit là d'un moyen permettant à un attaquant potentiel de contourner un contrôle basé sur la présence du mot clé 'script'.

Enfin, une autre vulnérabilité (remontée il y a peu par "Fortify Software" et "White Hat Security") est basée sur une faiblesse de la fonctionnalité "Same Origin Policy": le "JavaScript Hijacking" (voir la rubrique "Pour plus d'informations :" pour une description de cette vulnérabilité.

De façon plus générale, si les navigateurs actuels surveillent bien que les requêtes et les réponses HTTP vont et viennent bien d'un même site (principe du contrôle "Same Origin Policy"), et si le "JavaScript Hijacking" est désormais corrigé, on ne peut pas exclure que de nouvelles vulnérabilités de ce type soient découvertes (en particulier parce que chaque navigateur implémente de sa propre façon le contrôler de "Same Origin Policy").

 

Conclusion

En conclusion, cet article n'a pas pour vocation de dénigrer l'architecture AJAX.
Elle est en effet intéressante selon certains critères :

  • Amélioration des performances par le fait qu'elle permet de morceler les requêtes.
  • Amélioration du confort de l'utilisateur en permettant des traitements de présentation, comme de contrôle des erreurs de saisie.
  • Facilité de déploiement. Les technologies employées sont largement répandues et ne nécessitent, suivant les cas, pas d'installation de nouveaux logiciels sur les postes clients.

Elle est cependant potentiellement dangereuse et il faudra s'attacher à surveiller quelques points lors du développement d'une application utilisant ce type d'architecture.

Les règles de bonne pratique communément utilisées dans le développement d'applications web sont ici à reconduire :

  • Le serveur web doit être sécurisé. Ce qui inclut les binaires faisant tourner l'application, mais aussi le contenu (arborescence de pages du site).
  • Il faut filtrer les caractères/mots clés dangereux autant que possible.
  • Du point de vue du codage, il faut :
    • être vigilant sur les possibilités de "Cross Site Scripting" : pour ce faire, contrôler les pages de son site,
    • être vigilant sur les injections SQL lorsque l'application utilise une base de données (le problème se transpose au XML sur toute application échangeant sur XML, ou à tout contenu respectant une grammaire),
    • s'appuyer exclusivement sur des contrôles sécurité effectués coté serveur,
    • utiliser des "frameworks" qui sont préprogrammés pour se défendre contre les attaques (et donc éviter de re-développer un personnellement un mécanisme déjà fourni par un de ces "frameworks").
  • Bien que l'objet "XMLHttpRequest" ou l'interfaçage avec les "web services" ouvrent de larges perspectives, il ne faut pas présumer de la richesse de ces nouvelles fonctionnalités,

Coté client, il est important de surveiller les avis de vulnérabilité sur les navigateurs. Actuellement, il n'y a malheureusement pas de moyen de se prémunir contre les défauts (sécuritaires) de cette architecture. A moins d'interdire purement et simplement l'exécution du JavaScript (et des contrôles ActiveX pour certains navigateurs), mais, pour les internautes qui se sont habitués aux contenus dynamiques, un retour en arrière est difficile à imaginer.

Pour finir, il faut être bien conscient que la présence d'un pare-feu ne protège en rien contre les risques énoncés dans cet article, étant donné que tout le trafic passe dans des échanges HTTP traditionnels.

Coté client, il est toujours possible d'installer un antivirus qui bloque les scripts malveillants (comme celui d'un cheval de Troie par exemple). Mais pour qu'il soit efficace, il faut que la signature du code malveillant soit déjà référencée par l'éditeur.

En tout état de cause, il est recommandé de ne pas utiliser une architecture AJAX pour transmettre des données confidentielles.

Pour information, et pour les gens soucieux de vérifier les échanges HTTP, l’extension Firebug (http://extensions.geckozone.org/FireBug) pour les navigateurs Firefox permet, entre autres de vérifier l’objet "XMLHttpRequest". De plus, il semblerait que des ébauches de solution commencent à voir le jour : par exemple,  le scanner "Sprajax".


Pour plus d'informations :

 

Glossaire :

  • Ajax : Asynchronous JAvascript XML
  • CSS : Cascading Style Sheets
  • DOM : Document Object Model
  • HTML : HyperText Markup Language
  • HTTP : HyperText Transfer Protocol
  • XML : eXtensible Markup Language
  • XHTML : eXtensible HyperText Markup Language (réécriture du HTML avec une grammaire XML)
  • XSLT : eXtensible Stylesheet Language Transformation
  • XSS ou CSS : Cross Site Scripting
Précedent Précedent Suivant Suivant Imprimer Imprimer