1 – Vulnérabilités de type XSS et attaques par déni de service

Il existe de nombreuses vulnérabilités affectant les applications Web. Parmi elles, les vulnérabilités de type « Cross Site Scripting » (XSS) permettent d’exécuter du code arbitraire dans le navigateur d’un visiteur de site vulnérable. Récemment, une telle vulnérabilité a été exploitée sur un site Internet à fort trafic dans le but de réaliser une attaque par déni de service distribué (DDoS).

Vulnérabilité de type « Cross Site Scripting »

Les vulnérabilités de type « Cross Site Scripting » consistent à injecter des données dans une page web afin qu’elles soient interprétées par le navigateur. Les données injectées sont en général du code HTML ou JavaScript : le code injecté est ainsi exécuté chez le client. Une vulnérabilité de type XSS peut être exploitée pour divers objectifs :

  • modification du code de la page (modification des informations affichées, ajout de liens, etc.) ;
  • interception des données de formulaires (vol de mots de passe, etc.) ;
  • vol de cookies de session ;
  • etc.

Une vulnérabilité de type XSS se caractérise par l’exploitation des données brutes envoyées par l’utilisateur. Elles sont donc principalement présentes sur les sites utilisant du contenu généré par les utilisateurs (forums, blogs, sites de partage de médias, etc.). De façon plus générale, ce type de vulnérabilité existe potentiellement dès le moment où une donnée transmise par un client est utilisée sans vérification ou filtrage (par exemple, dans le cas d’un identifiant passé en paramètre d’une URL).

Le cas d’exploitation le plus fréquent se produit lorsque les paramètres passés à une page sont réutilisés sans être assainis au préalable. Dans ce cas, une personne malintentionnée peut écrire une URL particulière pointant vers la page vulnérable avec un paramètre GET contenant du code malveillant (en JavaScript le plus souvent). Cette URL est ensuite envoyée à la victime par des techniques de type hameçonnage. Le code passé en paramètre est alors exécuté chez la victime lorsque cette dernière clique sur le lien malveillant.

Par exemple, dans l’extrait de code PHP suivant, le contenu de la variable GET v est affiché tel que transmis :

<?php echo $_GET[‘v’]; ?>

Si le contenu de la variable v contient du code JavaScript encadré par la balise <script>, alors celui-ci sera exécuté dans le navigateur du client. Un des moyens de rendre ce code non vulnérable aux failles de type XSS est donc d’assainir le contenu de la variable $_GET[‘v’] lors de son utilisation (par exemple en remplaçant les < et > de la balise <script> par leurs entités HTML respective : &lt; et &gt;).

Il existe une catégorie spécifique de vulnérabilité de type XSS : les vulnérabilités XSS persistantes (ou stockées). Le principe est le même que celui évoqué précédemment à la différence que, dans ce cas, les données sont stockées de manière permanente dans l’application (par exemple : commentaire sur un article, nom d’utilisateur, etc.) : le code malveillant ainsi injecté sera alors exécuté sur chaque page utilisant les données le contenant.

Déni de service distribué basé sur une vulnérabilité XSS persistante

Le code injecté lors de l’exploitation d’une vulnérabilité de type XSS peut servir notamment à effectuer une requête vers une autre site Internet dans le but de le surcharger. Au début du mois d’avril 2014 une telle exploitation a été constatée sur un des sites de partage de vidéos les plus visités au monde.

Cette vulnérabilité était persistante et a permis à l’attaquant d’injecter du code Javascript dans la balise <img> affichant la photo de profil des utilisateurs. Ainsi, à chaque fois que la photo de profil associée à ce code malveillant était utilisée, le code injecté était exécuté par le navigateur affichant la page.

Le code incriminé consistait à effectuer une requête toutes les secondes vers un site Internet particulier afin de le surcharger. Le site vulnérable étant très largement visité, le nombre de requêtes a été assez important pour provoquer un déni de service, transformant alors malgré eux tous les visiteurs en acteurs d’une attaque DDoS.

Recommandations

Le CERT-FR souhaite rappeler que, dans le cadre des applications web, les traitements des données doivent tous être faits du côté du serveur. Les entrées en provenance des clients ne doivent pas être considérées comme fiables. Pour mémoire, l’ANSSI a publié un guide de recommandations pour la sécurisation des sites web.

Concernant les vulnérabilités de type XSS, le CERT-FR recommande ainsi d’échapper systématiquement toute donnée externe. Par exemple, dans le cas d’un script PHP générant du code HTML, l’échappement peut être effectué grâce à la fonction htmlspecialchars : cette fonction permet de convertir les caractères spéciaux dans l’entité HTML correspondante. Il convient aussi de vérifier que le format des données reçues correspond à celui attendu (par exemple, qu’une séquence numérique n’est composée que de chiffres) ; cela peut s’effectuer grâce à des expressions rationnelles.

Plus généralement, le CERT-FR recommande d’apporter un soin particulier dans le code applicatif manipulant des données transmises par un utilisateur. Cela se traduit notamment par le nettoyage et la vérification systématique de l’ensemble des données envoyées par un client avant toute utilisation (affichage ou requête par exemple).

Documentation

2 – Modification du logiciel OpenSSH pour les distributions Debian unstable

Une amélioration a récemment été apportée à la configuration du logiciel OpenSSH livré par Debian dans sa version 6.6p1-1.

En effet, l’option de configuration PermitRootLogin est désormais définie par défaut à without-password. Cette modification a pour conséquence d’interdire au compte root de s’authentifier sur un système via SSH avec un mot de passe.

Cette évolution n’est pour l’instant intégrée ni sur les distributions stables Debian, ni sur les autres distributions Linux et BSD. Toutefois d’autres mesures de durcissement peuvent être appliquées afin de réduire la surface d’attaque et limiter les accès frauduleux à un système via SSH, notamment :

  • le paramètre PermitRootLogin devrait être défini à No, afin d’interdire l’authentification avec le compte utilisateur root sur la machine ;
  • le serveur SSH doit uniquement être en écoute sur une adresse d’un réseau d’administration ;
  • sauf besoin dûment justifié, toute fonctionnalité de redirection de flux doit être désactivée, au niveau de la configuration du serveur SSH ainsi qu’au niveau du pare-feu local ;
  • l’authentification d’un utilisateur doit se faire à l’aide d’un des mécanismes suivants, par ordre de préférence : cryptographie asymétrique ECDSA, cryptographie asymétrique RSA, cryptographie symétrique via Kerberos, module PAM n’exposant pas le mot de passe utilisateur, et en dernier lieu par mot de passe.

L’ensemble de ces recommandations est détaillé dans la note technique « recommandations pour un usage sécurisé d'(Open)SSH », publiée par l’ANSSI le 21/01/2014.

Documentation

3 – Contrôle d’accès obligatoire sur les systèmes Linux

Le contrôle d’accès aux ressources sur les systèmes de type POSIX se base généralement sur un jeu de permissions (principalement lecture, écriture et exécution) associés à ces ressources. Ces permissions sont confrontées à l’identité d’exécution du processus lors de l’ouverture d’une ressource. Elles peuvent être modifiées par le propriétaire de la ressource ou par le super-utilisateur (root).

Ce principe est appelé contrôle d’accès discrétionnaire (DAC pour Discretionary Access Control). En cas de compromission d’un processus, l’attaquant peut accéder à l’ensemble des ressources autorisées par les permissions discrétionnaires.

Un système de contrôle d’accès obligatoire (MAC – Mandatory Access Control) permet à l’administrateur d’imposer une politique de contrôle d’accès au niveau du système, contrairement au contrôle d’accès discrétionnaire, où les permissions sont positionnées par le propriétaire de chaque ressource. Cette politique obligatoire se cumule au contrôle d’accès discrétionnaire classique.

Par ailleurs, les solutions techniques de contrôle d’accès obligatoire existantes pour les systèmes Linux permettent de contrôler plus finement les accès d’un processus aux ressources d’un système que les ACL discrétionnaires classiques (type de manipulation et portée de ces manipulations).

Il est notamment possible de restreindre le type d’action que peut effectuer un processus (ou une catégorie de processus) sur un sous-ensemble de ressources. Par exemple, un processus ne peut exécuter qu’une liste prédéfinie de programmes, ou ne peut réaliser que des opérations de lecture dans un répertoire donné.

Ainsi, en cas de compromission d’un processus, outre les restrictions d’accès discrétionnaires, le champ d’action de l’attaquant est restreint aux opérations autorisées par la politique MAC imposée par le système.

Systèmes de contrôle d’accès obligatoire sous Linux

Plusieurs solutions de contrôle d’accès obligatoire existent pour les systèmes Linux, dont les plus répandues sont :

  • SELinux : solution la plus riche en fonctionnalités (seule solution à proposer une gestion de labels multi-niveau), développée par la NSA, et disponible dans le noyau Linux vanilla ;
  • Smack : projet porté par Casey Schaufler, censé apporter une alternative simplifiée à SELinux, également disponible dans le noyau Linux vanilla ;
  • Grsecurity : projet porté par Brad Spengler. Les divergences de point de vue entre celui-ci et les mainteneurs du noyau Linux freinent l’intégration du projet à la branche principale du noyau ;
  • AppArmor : lancé par la société Immunix, le projet a été repris par Novell puis par Canonical. Les initiateurs de ce projet sont également à l’origine de la mise en œuvre de LSM dans le noyau Linux ;
  • Tomoyo : initié par des membres de la société NTT DATA, ce mécanisme se spécialise sur les contrôles basés sur la hiérarchie d’appels.

Selon la solution utilisée, la mise en Å“uvre du contrôle d’accès obligatoire repose sur la définition de politiques basées sur :

  • les rôles affectés aux utilisateurs et les contextes de sécurité associés aux processus et aux ressources (SELinux) : modèle dit RBAC ;
  • les labels (ou « types » dans le cas de SELinux) associés aux processus et aux ressources (Smack, SELinux) : modèle dit de « Type Enforcement » ;
  • les rôles affectés aux utilisateurs, les chemins des exécutables à l’origine des processus et les chemins de fichiers / répertoires accédés par ces processus (Grsecurity) ;
  • les chemins des exécutables et des fichiers / répertoires auxquels les processus associés accèdent (AppArmor, Tomoyo).

Solutions basées sur les labels

Les solutions SELinux et Smack reposent sur le principe des labels (Smack) ou types (SELinux) positionnés au niveau du système de fichiers. Du point de vue des « sujets » (processus), ces labels / types, positionnés sur les exécutables, déterminent une partie du contexte d’exécution (le « domaine » du processus, dans la terminologie SELinux).

Les labels / types marquent par ailleurs les « objets » (fichiers, processus, sockets, etc.), afin de permettre de les référencer à travers la politique d’accès. La politique en question définit les droits d’accès des sujets vis-à-vis des objets (lecture, écriture sur les fichiers, réception / émission de données sur les sockets, etc.).

Solutions basées sur les chemins

Les solutions AppArmor et Tomoyo reposent sur les chemins des exécutables pour l’application de règles de contrôle d’accès aux ressources du système (fichiers, réseau, variables d’environnement, etc.). Tomoyo permet en outre de spécifier des critères supplémentaires liés au contexte d’exécution. Par exemple, la politique concernant un exécutable peut être différente selon l’identité d’exécution du processus. Ces systèmes fonctionnent par liste blanche pour les processus concernés par la politique de sécurité, c’est-à-dire que tout ce qui n’est pas explicitement autorisé est interdit.

Ces solutions possèdent intrinsèquement des limitations : en effet, il suffirait à un attaquant de créer un lien dur (hardlink) vers l’exécutable pour contourner les restrictions appliquées à cet exécutable ou de remplacer des fichiers dont l’accès est autorisé par la politique par des liens durs vers des fichiers illégitimes. De tels contournements sont également envisageables à travers des points de montage illégitimes.

Les développeurs de Tomoyo font toutefois remarquer qu’afin de s’affranchir de cette limitation, il suffit d’interdire en amont la création de hardlinks, à travers la politique Tomoyo elle-même, ce qui peut s’avérer fastidieux.

Le mode de fonctionnement de Grsecurity est quelque peu différent. La définition de la politique de contrôle d’accès de Grsecurity est basée sur des chemins, mais ceux-ci sont traduits par Grsecurity en numéros d’inode lors du démarrage du système. Ces numéros d’inodes font ensuite exclusivement référence pour l’application de la politique.

Ceci permet de se prémunir contre les tentatives de contournements précitées, car les inodes des liens durs utilisés par l’attaquant seront différentes des inodes référencées par la politique. Toutefois, le comportement de Grsecurity est différent pour les règles de contrôle d’accès faisant usage de caractères génériques (wildcards). En effet, de tels motifs ne peuvent être résolus au démarrage et sont donc évalués en temps réel lors du fonctionnement du système, sur la seule base du chemin de fichier. Les règles Grsecurity utilisant des caractères génériques sont ainsi soumises aux mêmes limitations que les mécanismes Tomoyo et AppArmor, en matière de contournement du contrôle d’accès par des liens durs ou des points de montage illégitimes.

Modalités de déploiement

Le système Grsecurity est disponible sous forme de patch pour le code source de Linux. N’étant pas présent par défaut sur les distributions GNU/Linux les plus courantes, sa mise en place nécessite l’application du patch sur les sources du noyau, puis la compilation de ce dernier, ce qui complexifie son maintien en conditions de sécurité (Outre le contrôle d’accès obligatoire, Grsecurity met en œuvre divers mécanismes de sécurité malheureusement absents de la version vanilla du noyau Linux).

À l’inverse, les systèmes de contrôle d’accès SELinux, Smack, AppArmor et Tomoyo s’intègrent au noyau Linux au travers des LSM (Linux Security Modules). De nombreuses distributions sont livrées avec un noyau précompilé avec le support de certains des systèmes MAC cités ci-dessus. Par exemple, Debian GNU/Linux supporte les systèmes SELinux, AppArmor et Tomoyo, quand Fedora supporte SELinux uniquement.

Le déploiement d’un système de contrôle d’accès obligatoire est dans ce cas facilité, puisqu’il suffit d’activer la prise en compte du système au niveau de la ligne de démarrage du noyau Linux. La recompilation du noyau n’étant pas nécessaire, les mises à jour de ce dernier pourront être effectuées au travers du système de gestion de paquets de la distribution.

Conclusion

La diversité de ces systèmes permet à un administrateur de choisir le système de contrôle d’accès le plus adapté à ses besoins. Au-delà de la distinction entre MAC « classique » et RBAC, le choix doit être fait entre les deux grandes familles de contrôle d’accès : les systèmes basés sur les labels, et les systèmes basés sur les noms et chemins des exécutables et des ressources.

Dans le prochain article sur le sujet, les modalités de mise en œuvre d’une politique Tomoyo ainsi qu’un exemple concret de politique seront présentées.

Rappel des avis émis

Dans la période du 14 au 20 avril 2014, le CERT-FR a émis les publications suivantes :