Ghost est une faille de sécurité basée sur un dépassement de mémoire tampon causé par les fonctions « gethostbyname » , « gethostbyname2 », « gethostbyaddr » des librairies glibC 2.2 et celles antérieures à la version 2.18 de Linux. Cette faille permet à un attaquant d’exécuter, en fonction du contexte, du code arbitraire et ainsi de prendre le contrôle du système. Elle concerne à la fois les serveurs, les routeurs ou encore les NAS utilisant Linux.
Historique La première apparition de ce type de faille dans glibc remonte à 2000 et avait été corrigée le , entre les versions 2.17 et 2.18 de glibc. Toutefois, le risque pour la sécurité des systèmes ayant été sous-évalué, l’essentiel des distributions Linux stables bénéficiant d'un support n’ont pas aussitôt appliqué de correction à leur librairie. La raison avancée par les éditeurs est celle d’un problème de compatibilité.
Ghost a été découvert par la société Qualys, fournisseur d’information de sécurité, en . Avant de divulguer la faille officiellement le , Qualys a signalé le problème aux éditeurs de distributions Linux, qui ont rapidement mis au point des correctifs. Des mises à jour sont notamment disponibles pour Debian, Ubuntu et Red Hat.. Compte tenu du nombre d’applications basées sur glibc, Ghost est depuis le considéré comme une vulnérabilité sévère qui doit être corrigée immédiatement. La vulnérabilité Ghost est aujourd’hui classifiée par la NCASNCAS pour National Cyber Awareness System qui pourrait être traduit par Système National de Cyber-sensibilisation. américaine à la valeur 10, c’est-à-dire au niveau haut, et porte la référence CVE-2015-0235..
Sévérité CVSS (version 2.0) Score: 10.0 Score d'impact: 10.0 Score d'exploitabilité: 10.0Metriques CVSS Vecteur d'accès: Exploitable par le réseau Complexité: Basse Authentification: Non requis pour exploiter Type d'impact: Permet la divulgation non autorisée d'informations ; Permet une modification non autorisée ; Permet l'interruption de service
Principe
Ghost exploite une faille logée dans la libraire GNU/Linux nommée glibC. Cette dernière, intégrée dans toutes les distributions de Linux, permet de gérer les appels système de bas niveau, telles l’allocation d’espace mémoire, l’ouverture des fichiers, etc. La vulnérabilité est basée sur un dépassement de mémoire tampon dans les fonctions « gethostbyname » ou « gethostbyaddr » impliquées dans le mécanisme de résolution de nom DNS. Ces fonctions sont appelées par les applications Linux pour gérer les connexions Internet, à l’image des serveurs de messagerie par exemple.
La fonction « gethostbyname() » renvoie une structure de type hostent pour l'hôte « name ». La chaîne « name » est soit un nom d'hôte, soit une adresse IPv4 en notation pointée standard, soit une adresse IPv6 avec la notation points-virgules et points. La fonction gethostbyaddr() renvoie une structure du type hostent pour l'hôte d'adresse « addr ». Les types d'adresse valides sont IPv4 ou IPv6. L’objectif du dépassement de tampon est la mise en échec de la fonction en écrivant dans sa zone mémoire temporaire (buffer) plus de données qu’elle ne peut en contenir, afin d’écraser son code et de lui substituer du code malveillant.
Le dépassement de tampon
Lors de l’appel de la fonction, le programme empile le pointeur d’instruction (@EIPEIP pour Instruction Pointer. Le registre EIP contient l’offset de la prochaine instruction à exécuter.) dans la pile. Ceci afin d’avoir l’adresse de retour après l’exécution de la fonction et ainsi enchainer vers l’instruction suivante. Par ailleurs, l’appel de la fonction va généralement créer sa propre pile dans la pile pour simplifier sa gestion d’adressage. Elle va alors empiler l’adresse absolue de la base de la pile (@EBPEBP pour Frame Base Pointer. Ce registre sert à pointer sur une donnée dans la pile.) et affecter la valeur du pointeur de la pile (@ESPESP pour Stack Pointer. Ce registre 32 bits contient le déplacement pour atteindre le sommet de la pile.) à celle de la base(@EBP pour la fonction). Ainsi, au dépilement après l’exécution de la fonction, l’adresse absolue de la base sera réaffectée et la pile réinitialisée.
Il faut savoir toutefois que l’allocation de la mémoire temporaire se décompose en deux parties : Le tastas: heap en anglais. qui correspond à la zone mémoire réservée temporairement pour le code, et les variables globales. Le tas se situe dans la partie d’adressage basse. La pilePile: stack en anglais. qui correspond à la zone mémoire réservée dans les cadres d’appel à des fonctions (ou procédures), et les variables d’environnement. La pile se situe dans la partie d’adressage haute. La grande différence entre ces deux zones est le sens d’empilement : il est croissant pour le tas, et décroissant pour la pile. Pour la pile, la première adresse empilée possède la valeur la plus grande, et la dernière adresse empilée possède la valeur la plus faible. Comme le sens de lecture de la mémoire reste dans le sens croissant, un dépassement de tampon dans la pile permet alors l’écrasement des registres contenant EBP et EIP. Par ce principe, un pirate peut remplacer la valeur d’EIP par une adresse pointant vers du code malveillant logé dans la zone tampon utilisée. Néanmoins, cela demande au pirate de connaitre l’adresse exacte de la pile pour assurer le saut d’adresse utilise à l’exécution de son code arbitraire.
Ghost dans les faits Les fonctions gethostbyname() et gethostbyaddr() provoquent le débordement de tampon lors de l’appelle à une autre fonction __nss_hostname_digits_dots(). Celle-ci est appelée pour vérifier l’hôte ‘name’. Cette fonction contient en fait une erreur de code dans le calcul de la taille de son buffer si ‘name’ est une adresse IP.
En effet, son buffer est fixé à une taille size_needed ne considérant que trois entités de registre mémoire : host_addr, h_addr_ptrs et name. Toutefois , la fonction charge dans le buffer quatre entités de registre mémoire : host_addr, h_addr_ptrs , name et h_alias_ptr. C’est dans ce cas que le buffer peut s’avérer trop petit pour contenir un hôte 'name' très grand et ayant la forme d’une adresse IP « a.b.c.d », « a.b.c », « a.b », ou « a ».
Impact
Pour le mois de , les logiciels identifiés vulnérables sont : Clockdiff, Procmail (au travers des fonctionnalités comsat/biff), , Exim (lorsque les options « helo_verify_hosts » et « helo_try_verify_hosts » sont activées, ce qui n'est pas le cas par défaut), L’interpréteur PHP.
À noter aussi que les sites qui utilisent Wordpress (système de gestion de contenu CMS) pourraient être vulnérables avec la page « xmlrpc.php » par défaut qui utilise la fonctionnalité de notification « pingback ».
À ce titre, les distributions suivantes sont identifiées comme vulnérables : OS DistributionsVersionsLinuxRed Hat Enterprise5.x, 6.x et 7.xLinuxCentOS 5.x, 6.x & 7.xLinuxUbuntu 10.04, 12.04 LTSLinuxDebian7.xLinuxFedora19 et ultérieursLinuxSUSE11 et ultérieursLinuxArch Linux avec Gblicinférieure ou égale à 2.18-1LinuxMint13.0
Depuis 2013, ce type de vulnérabilité, désignée "A9 - Utilisation de composants avec des vulnérabilités connues", est entré dans le top10 d'OWASP (Open Web Application Security Project). Cela s’explique par le fait que les développements utilisent de plus en plus des composants. Par conséquent, l’usage de composants vulnérables est lui aussi de plus en plus risqué.
POC
Plusieurs preuves de concept sont publiées : Pour PHP, la commande suivante permet de vérifier si la vulnérabilité existe en rapportant un message d’erreur
php -r '$e="0";for($i=0;$i<2500;$i++){$e="0$e";gethostbyname($e); }'
Pour Wordpress, la méthode « pingback » est à désactiver car elle emploie « gethostbyname ».
Pour vérifier si son système est concerné par la vulnérabilité Ghost, il est d’abord nécessaire de connaitre sa version de glibc grâce à la commande suivante : ldd –version
L'éditeur en sécurité Qualys propose un outillage pour tester son système rapidement.. Pour tester la faille, il utilise une détection de tampon par méthode du canari. Le code: fixe la taille de deux registres contigus de type struct. affecte un pointeur de buffer dans le premier registre. affecte une chaîne de caractères CANARY dans le deuxième registre. calcule la taille maximale d’une variable name relative à la taille du premier registre. affecte à cette variable des ‘0’ et la termine par ‘\0’ pour qu’elle ait l’aspect d’une adresse IP, utilise la variable name, et le pointeur de buffer en argument à la fonction gethostbyname_r(). teste si le contenu du deuxième registre contient toujours la chaine de caractères ‘CANARY’. Si les chaines sont différentes, le système est considéré vulnérable.
Exploit
À la date de publication de cet article, seul l’exploit fourni par Qualys est disponible au public, mais il ne provoque seulement qu’un déni de service. En effet, aucun code d'exploitation n'est encore proposé pour prendre le contrôle d'un système à distance. Qualys a annoncé disposer d'un outil permettant de prendre le contrôle d'un serveur Exim à distance. Cependant, ce code ne sera publié que lorsque Qualys estimera que la majorité des systèmes exposés sur Internet seront corrigés.
L'exploit Exim Le serveur de messagerie Exim est exploitable à distance si configuré pour effectuer des contrôles de sécurité supplémentaires sur les commandes de salutation HELO et EHLO (helo_verify) envoyés par l’expéditeur de courrier.
Premièrement, la méthode d'exploit consiste à réaliser un débordement de tampon dans le tas de gethostbyname et écraser partiellement le champ du prochain bloc contigu de mémoire avec une taille légèrement plus grande (). Cela entraine une allocation mémoire qui est agrandi artificiellement. Ce bloc de mémoire est géré par Malloc de GlibC et chevauche un autre bloc mémoire qui est géré par l’allocateur mémoire interne à Exim. Dans ce bloc agrandi, la technique va être d’allouer partiellement un morceau de mémoire pour y écrire du code arbitraire et écraser le début du contenu du bloc mémoire d’Exim. Cela amène alors dans une primitive où il est possible d’écrire n’importe quoi n’importe où, car on peut contrôler à la fois le pointeur de la prochaine zone mémoire retourné par l’allocateur d’Exim et les données qui lui sont affectées (une chaine de caractères terminée par un null, l’argument d’une commande SMTP qu’on envoie à Exim). Par conséquent, la primitive est utilisée pour aller écraser la configuration de l’environnement d’exécution (runtime) d’Exim qui est mis en cache dans le tas. Le but est d’écraser plus précisément la liste des contrôles d’accès (ACLs) d’Exim et de pouvoir exécuter des commandes arbitraires grâce à des extensions d’Exim telle ${run<command> <args<}}.
Le succès de cet exploit dépend d'un élément d’information important: l'adresse de l'environnement d’exécution de la configuration d'Exim dans le tas.
Palliatifs
Tous les éditeurs Linux ont publié un correctif : Ubuntu Linux Redhat Debian Oracle Centos SuSe Slackware
Les constructeurs de matériels comme les NASNAS pour Network Access Server qui pourrait être traduit par Serveur d'accès réseau. ou les routeurs utilisant une version de Linux impactées publient progressivement des patchs.
Il est important de noter que les fonctions « gethostbyname() » et « gethostbyaddr() » sont obsolètes. Les applications devraient plutôt utiliser les fonctions « getaddrinfo() » et « getnameinfo() » à la place et ainsi éviter la vulnérabilité. Le conseil majeur pour se prémunir contre Ghost est d’appliquer le plus rapidement possible les patchs fournis par les éditeurs.